#ifndef USRAI_H
#define USRAI_H

#include "AI.h"
#include <vector>
#include <map>
#include <set>
#include <utility>
#include <ctime>
#include <unordered_set>
#include <string>
#include <queue>

extern tagGame tagUsrGame;
extern ins UsrIns;

#ifndef MAPPATTERN_SHALLOWS
#define MAPPATTERN_SHALLOWS 3
#endif

class UsrAI : public AI
{
public:
    enum GameStage {
        STAGE_INITIAL,
        STAGE_BUILD_HOUSES,
        STAGE_POPULATION_GROWTH,
        STAGE_COLLECT_RESOURCES,
        STAGE_BUILD_REQUIRED_BUILDINGS,
        STAGE_UPGRADE_AGE,
        STAGE_BUILD_FISHING_BOAT,
        STAGE_AFTER_UPGRADE,
        STAGE_BUILD_WARSHIPS,
        STAGE_EXPLORE,
        STAGE_BUILD_ARMY,
        STAGE_LAND_INVASION,
        STAGE_COLLECT_GOLD
    };

    enum TransportState {
        TRANSPORT_IDLE = 0,
        TRANSPORT_LOADING = 1,
        TRANSPORT_DEPARTING = 2,
        TRANSPORT_RETURNING = 3,
        TRANSPORT_RELOCATING = 4
    };
    void executeTransportReturn(const tagFarmer* transport, const tagInfo& info);
    static std::map<std::pair<int,int>, int> failedDockPositions;
    static std::map<std::pair<int,int>, int> successfulDockPositions;
    static int maxDockRetries;
    static int dockBuildAttemptFrame;
    static int dockBuildCooldown;
    static std::vector<std::pair<int, int>> attemptedFishPositions;

    static std::map<int, std::pair<int, int>> fleetPatrolTargets;
    static std::vector<std::pair<int, int>> explorationZones;
    static bool explorationZonesInitialized;

    static int villagersTransported;
    static int maxVillagersToTransport;

    static tagInfo prevInfo;
    static int center_x, center_y;
    static bool centerInitialized;
    static std::set<std::pair<int, int>> occupiedPositions;
    static GameStage currentStage;

    static int houseCount;
    static int housesUnderConstruction;
    static const int TARGET_HOUSES = 4;
    static int houseBuilderSN;
    static int searchRadius;
    static int lastHouseX, lastHouseY;

    static int targetPopulation;
    static time_t lastVillagerProductionTime;
    static bool buildingHousesInProgressInPopulationStage;
    static std::unordered_set<int> ordinaryVillagers;

    static bool stockBuilt;
    static bool dockBuilt;
    static bool fishingBoatBuilt;
    static bool granaryBuilt;
    static bool marketBuilt;
    static bool armyCampBuilt;
    static bool rangeBuilt;
    static bool stableBuilt;
    static bool woodCuttingUpgraded;
    static bool toolUseUpgraded;
    static int dockBuilderSN;
    static bool dockBuilderReserved;
    static bool dockConstructionStarted;
    static int totalDocksPresent;
    static int completedDocksCount;
    static const int TARGET_DOCKS_NUM = 2;
    static bool farmBuilt;
    static int farmsBuilt;
    static const int TARGET_FARMS = 1;
    static bool warshipProductionTriggered;

    static int fishingBoatCount;
    static const int TARGET_FISHING_BOATS = 4;
    static const int TARGET_BOATS_PER_DOCK = 2;
    static std::map<int, int> dockFishingBoatCount;

    static int warshipCount;
    static const int TARGET_WARSHIPS = 10;
    static const int TARGET_WARSHIPS_PER_DOCK = 5;
    static std::map<int, int> dockWarshipCount;

    static int transportShipCount;
    static const int TARGET_TRANSPORT_SHIPS = 1;
    static std::map<int, int> dockTransportShipCount;

    static std::map<int, int> transportShipStates;
    static std::map<int, int> transportLastCommandFrame;
    static std::map<int, int> transportLoadingStartFrame;
    static const int TRANSPORT_COMMAND_COOLDOWN = 30;
    static const int TRANSPORT_LOADING_TIMEOUT = 1000;

    static std::vector<std::vector<int>> warshipFleets;
    static std::map<int, std::pair<int, int>> fleetExplorationTargets;
    static std::map<int, int> fleetAttackTargetsSN;
    static std::unordered_set<int> assignedWarships;
    static bool unifiedFleetMode;
    static std::pair<int, int> fleetExplorationCenter;
    static int fleetExplorationRadius;
    static int currentEnemyTargetSN;
    static bool fleetInCombat;
    static int combatStartFrame;
    static std::vector<std::pair<int, int>> exploredSectors;
    static bool fleetsFormed;

    static int clubmanCount;
    static int slingerCount;
    static int bowmanCount;
    static int scoutCount;
    static const int TARGET_CLUBMAN = 10;
    static const int TARGET_SLINGER = 6;
    static const int TARGET_BOWMAN = 8;
    static const int TARGET_SCOUT = 4;
    static std::vector<int> landArmy;
    static std::unordered_set<int> boardedUnits;

    static bool enemyContinentFound;
    static int enemyContinentX, enemyContinentY;
    static std::vector<std::pair<int, int>> enemyLandPositions;
    static std::vector<std::pair<int, int>> landingPositions;
    static int selectedLandingX, selectedLandingY;

    static bool goldFound;
    static std::vector<std::pair<int, int>> goldPositions;
    static int goldCollected;
    static const int TARGET_GOLD = 2500;
    static std::unordered_set<int> goldMiners;
    static int transportedVillagers;
    static const int TARGET_GOLD_MINERS = 15;

    static int foundDockX, foundDockY;
    static bool dockPositionFound;
    static std::vector<std::pair<int, int>> fishPositions;
    static bool fishPositionsInitialized;

    static int villagersToProduceAfterUpgrade;
    static int villagersProducedAfterUpgrade;
    static int existingStocksAtUpgrade;
    static const int TARGET_TOTAL_STOCKS = 2;
    static int toolAgeBuilderSN;
    static bool toolAgeBuilderAssigned;
    static int housesToBuildAfterUpgrade;
    static int housesBuiltAfterUpgrade;

    static bool upgradeStarted;
    static bool ageUpgraded;
    static int upgradeBuilderSN;

    static std::map<int, int> unitCombatTargets;
    static std::set<int> defeatedEnemies;
    static bool combatMode;

    static bool toolAgeInitialized;
    static int toolAgePhase;
    static bool toolAgeBuilderBusy;
    static int toolAgeStocksBuilt;
    static int toolAgeHousesBuilt;

    UsrAI(){this->id=0;}
    ~UsrAI(){}

private:
    // 统一运输船管理
    void manageTransportShips(const tagInfo& info);
    bool canControlTransport(int transportSN, const tagInfo& info);
    void updateTransportState(int transportSN, TransportState newState, const tagInfo& info);
    void handleTransportIdle(const tagFarmer* transport, const tagInfo& info);
    void handleTransportLoading(const tagFarmer* transport, const tagInfo& info);
    void handleTransportDeparture(const tagFarmer* transport, const tagInfo& info);
    void handleTransportReturn(const tagFarmer* transport, const tagInfo& info);
    void handleTransportRelocating(const tagFarmer* transport, const tagInfo& info);
    void relocateTransportToOcean(const tagFarmer* transport, const tagInfo& info);
    void moveTransportToCoast(const tagFarmer* transport, const tagInfo& info);
    void loadVillagersOntoSingleTransport(const tagFarmer* transport, const tagInfo& info);

    std::pair<int, int>getWarshipFleetCenter(const tagInfo& info);
    bool findNearestCoastalToFleet(int& x, int& y, const std::pair<int, int>& fleetPos, const tagInfo& info);
    bool attemptBuildDock(const tagInfo& info);
    bool ensureDockBuilder(const tagInfo& info, tagFarmer*& builderFarmer);
    bool findAllDockPositionsNearFish(std::vector<std::pair<int, int>>& positions,
                                      const std::pair<int, int>& fishPos,
                                      const tagInfo& info);
    double calculateDockPositionScore(int x, int y,
                                     const std::pair<int, int>& fishPos,
                                     const tagInfo& info);
    void logBuildError(int errorCode, int x, int y);
    void moveBuilderCloser(tagFarmer* builder, int targetX, int targetY);
    bool attemptBuildDockAnywhere(const tagInfo& info, tagFarmer* builder);
    void attemptBuildStock(const tagInfo& info);
    bool findHomeCoastalLandPosition(int& x, int& y, const tagInfo& info);
    int getDistanceToNearestOcean(int x, int y, const tagInfo& info);
    bool findHomeCoastalPosition(int& x, int& y, const tagInfo& info);
    std::pair<int, int> getUnifiedFleetExplorationTarget(const tagInfo& info);
    void initializeExplorationZones(const tagInfo& info);
    bool findValidExplorationTarget(int fleetIndex, int& targetX, int& targetY, const tagInfo& info);
    std::pair<int, int> getPatrolTarget(int fleetIndex, const tagInfo& info);
    bool isValidOceanPosition(int x, int y, const tagInfo& info);
    bool isPositionNearMapEdge(int x, int y);
    void initializeToolAge(const tagInfo& info);
    bool assignToolAgeBuilder(const tagInfo& info);
    void handleToolAgeConstruction(const tagInfo& info);
    bool checkToolAgeCompletion(const tagInfo& info);

    bool isLand(int type);
    bool isOcean(int type);
    bool isMapCellLand(int x, int y, const tagInfo& info);
    bool isCellAdjacentToLand(int cx, int cy, const tagInfo& info);
    int countAdjacentLand(int cx, int cy, const tagInfo& info);
    bool isPositionReachable(int x, int y, const tagInfo& info);

    bool isTooCloseToExistingDocks(int newDockX, int newDockY, const tagInfo& info);
    bool isPositionValidForBuilding(int x, int y, int width, int height, int buildingType, const tagInfo& info);
    bool isPositionValidForHouse(int x, int y, const tagInfo& info);
    bool findNearbyPosition(int& x, int& y, const tagInfo& info, int width = 2, int height = 2, int buildingType = -1);
    bool findBestStockPosition(int& x, int& y, const tagInfo& info);

    bool findCoastalPositionNearCenter(int& x, int& y, const tagInfo& info, const std::set<std::pair<int, int>>& excludedPositions);
    bool findDockPositionNearFish(int& x, int& y, const std::pair<int, int>& targetFishPos, const tagInfo& info, const std::set<std::pair<int, int>>& excludedPositions);
    bool isDockNearFish(const std::pair<int, int>& fishPos, const tagInfo& info);
    bool findCoastalLandingPosition(int& x, int& y, const tagInfo& info);

    void assignTasksToVillagersWithLimits(const tagInfo& info, bool reserveOneIdleForDock);
    int findNearestResource(const tagFarmer& farmer, int resourceType, const tagInfo& info, const std::unordered_set<int>& excludedSNs);
    void produceVillagers(const tagInfo& info);

    void assignFishingBoatsToFishResources(const tagInfo& info);
    void formWarshipFleets(const tagInfo& info);
    void manageTransportShipProduction(const tagInfo& info);

    void initializeCenter(const tagInfo& info);
    void buildHousesPhase(const tagInfo& info);
    void populationGrowthPhase(const tagInfo& info);
    void collectResourcesPhase(const tagInfo& info);
    void buildRequiredBuildingsPhase(const tagInfo& info);
    void upgradeAgePhase(const tagInfo& info);
    void buildFishingBoatPhase(const tagInfo& info);
    void afterUpgradePhase(const tagInfo& info);
    void buildWarshipsPhase(const tagInfo& info);
    void explorePhase(const tagInfo& info);
    void buildArmyPhase(const tagInfo& info);
    void landInvasionPhase(const tagInfo& info);
    void collectGoldPhase(const tagInfo& info);

    void initializeFishPositions(const tagInfo& info);
    void scanForEnemyContinent(const tagInfo& info);
    void scanForGold(const tagInfo& info);
    void manageArmyProduction(const tagInfo& info);
    void loadArmyOntoTransports(const tagInfo& info);
    void loadVillagersOntoTransports(const tagInfo& info);  // 保留原函数声明
    void assignTransportShipsToShore(const tagInfo& info);  // 保留原函数声明
    void manageCombat(const tagInfo& info);
    void transportVillagersToGold(const tagInfo& info);
    bool findSafeLandingPosition(int& x, int& y, const tagInfo& info);
    void protectGoldMiners(const tagInfo& info);

    void processData() override;

    tagInfo getInfo(){return tagUsrGame.getInfo();}
    int AddToIns(instruction ins) override
    {
        UsrIns.lock.lock();
        ins.id=UsrIns.g_id;
        UsrIns.g_id++;
        UsrIns.instructions.push(ins);
        UsrIns.lock.unlock();
        return ins.id;
    }
    void clearInsRet() override{tagUsrGame.clearInsRet();}
};

#endif



#include "UsrAI.h"
#include <iostream>
#include <algorithm>
#include <ctime>
#include <sstream>
#include <unordered_set>
#include <string>
#include <climits>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <queue>
#define ACTION_OK 0
using namespace std;
tagGame tagUsrGame;
ins UsrIns;
std::map<int, int> UsrAI::transportShipStates;
std::map<int, int> UsrAI::transportLastCommandFrame;
std::map<int, int> UsrAI::transportLoadingStartFrame;
std::map<std::pair<int,int>, int> UsrAI::failedDockPositions;
std::map<std::pair<int,int>, int> UsrAI::successfulDockPositions;
int UsrAI::maxDockRetries = 3;
int UsrAI::dockBuildAttemptFrame = 0;
int UsrAI::dockBuildCooldown = 10;
std::vector<std::pair<int, int>> UsrAI::attemptedFishPositions;
bool UsrAI::warshipProductionTriggered = false;
bool UsrAI::farmBuilt = false;
int UsrAI::farmsBuilt = 0;
bool UsrAI::unifiedFleetMode = true;
std::pair<int, int> UsrAI::fleetExplorationCenter = {64, 64};
int UsrAI::fleetExplorationRadius = 20;
int UsrAI::currentEnemyTargetSN = -1;
bool UsrAI::fleetInCombat = false;
int UsrAI::combatStartFrame = 0;
std::vector<std::pair<int, int>> UsrAI::exploredSectors;
std::map<int, std::pair<int, int>> UsrAI::fleetPatrolTargets;
std::vector<std::pair<int, int>> UsrAI::explorationZones;
bool UsrAI::explorationZonesInitialized = false;
int UsrAI::villagersTransported = 0;
int UsrAI::maxVillagersToTransport = 5;
tagInfo UsrAI::prevInfo;
int UsrAI::center_x = 0;
int UsrAI::center_y = 0;
bool UsrAI::centerInitialized = false;
set<pair<int, int>> UsrAI::occupiedPositions;
int UsrAI::houseCount = 0;
int UsrAI::housesUnderConstruction = 0;
UsrAI::GameStage UsrAI::currentStage = UsrAI::STAGE_INITIAL;
int UsrAI::searchRadius = 1;
int UsrAI::lastHouseX = -1;
int UsrAI::lastHouseY = -1;
int UsrAI::houseBuilderSN = -1;

int UsrAI::targetPopulation = 0;
time_t UsrAI::lastVillagerProductionTime = time(nullptr);
bool UsrAI::buildingHousesInProgressInPopulationStage = false;

bool UsrAI::stockBuilt = false;
bool UsrAI::dockBuilt = false;
bool UsrAI::fishingBoatBuilt = false;
bool UsrAI::ageUpgraded = false;
int UsrAI::dockBuilderSN = -1;
bool UsrAI::dockBuilderReserved = false;
bool UsrAI::dockConstructionStarted = false;
int UsrAI::totalDocksPresent = 0;
int UsrAI::completedDocksCount = 0;

int UsrAI::fishingBoatCount = 0;
std::map<int, int> UsrAI::dockFishingBoatCount;

int UsrAI::warshipCount = 0;
std::map<int, int> UsrAI::dockWarshipCount;

int UsrAI::transportShipCount = 0;
std::map<int, int> UsrAI::dockTransportShipCount;

std::vector<std::vector<int>> UsrAI::warshipFleets;
std::map<int, std::pair<int, int>> UsrAI::fleetExplorationTargets;
std::map<int, int> UsrAI::fleetAttackTargetsSN;
std::unordered_set<int> UsrAI::assignedWarships;
bool UsrAI::fleetsFormed = false;

int UsrAI::foundDockX = -1;
int UsrAI::foundDockY = -1;
bool UsrAI::dockPositionFound = false;

std::vector<std::pair<int, int>> UsrAI::fishPositions;
bool UsrAI::fishPositionsInitialized = false;
std::unordered_set<int> UsrAI::ordinaryVillagers;

int UsrAI::villagersToProduceAfterUpgrade = 0;
int UsrAI::villagersProducedAfterUpgrade = 0;
int UsrAI::existingStocksAtUpgrade = 0;

const int MAX_HOUSE_SEARCH_RADIUS = 15;

int UsrAI::toolAgeBuilderSN = -1;
bool UsrAI::toolAgeBuilderAssigned = false;
int UsrAI::housesToBuildAfterUpgrade = 4;
int UsrAI::housesBuiltAfterUpgrade = 0;

bool UsrAI::granaryBuilt = false;
bool UsrAI::marketBuilt = false;
bool UsrAI::armyCampBuilt = false;
bool UsrAI::rangeBuilt = false;
bool UsrAI::stableBuilt = false;
bool UsrAI::woodCuttingUpgraded = false;
bool UsrAI::toolUseUpgraded = false;

bool UsrAI::upgradeStarted = false;
int UsrAI::upgradeBuilderSN = -1;

int UsrAI::clubmanCount = 0;
int UsrAI::slingerCount = 0;
int UsrAI::bowmanCount = 0;
int UsrAI::scoutCount = 0;
std::vector<int> UsrAI::landArmy;
std::unordered_set<int> UsrAI::boardedUnits;

bool UsrAI::enemyContinentFound = false;
int UsrAI::enemyContinentX = -1;
int UsrAI::enemyContinentY = -1;
std::vector<std::pair<int, int>> UsrAI::enemyLandPositions;
std::vector<std::pair<int, int>> UsrAI::landingPositions;
int UsrAI::selectedLandingX = -1;
int UsrAI::selectedLandingY = -1;

bool UsrAI::goldFound = false;
std::vector<std::pair<int, int>> UsrAI::goldPositions;
int UsrAI::goldCollected = 0;
std::unordered_set<int> UsrAI::goldMiners;
int UsrAI::transportedVillagers = 0;

std::map<int, int> UsrAI::unitCombatTargets;
std::set<int> UsrAI::defeatedEnemies;
bool UsrAI::combatMode = false;

bool UsrAI::toolAgeInitialized = false;
int UsrAI::toolAgePhase = 0;
bool UsrAI::toolAgeBuilderBusy = false;
int UsrAI::toolAgeStocksBuilt = 0;
int UsrAI::toolAgeHousesBuilt = 0;

bool UsrAI::isLand(int type) {
    return type == MAPPATTERN_GRASS || type == MAPPATTERN_SHALLOWS;
}

bool UsrAI::isOcean(int type) {
    return type == MAPPATTERN_OCEAN;
}

bool UsrAI::isMapCellLand(int x, int y, const tagInfo& info) {
    if (x < 0 || y < 0 || x >= 128 || y >= 128) {
        return false;
    }
    return this->isLand((*info.theMap)[x][y].type);
}

bool UsrAI::isCellAdjacentToLand(int cx, int cy, const tagInfo& info) {
    const int offsets[4][2] = {
        {-1, 0}, {1, 0}, {0, -1}, {0, 1}
    };
    for (const auto& offset : offsets) {
        int adjX = cx + offset[0];
        int adjY = cy + offset[1];
        if (adjX >= 0 && adjX < 128 && adjY >= 0 && adjY < 128) {
            if (this->isMapCellLand(adjX, adjY, info)) {
                return true;
            }
        }
    }
    return false;
}

int UsrAI::countAdjacentLand(int cx, int cy, const tagInfo& info) {
    int count = 0;
    const int offsets[8][2] = {
        {-1, 0}, {1, 0}, {0, -1}, {0, 1},
        {-1, -1}, {-1, 1}, {1, -1}, {1, 1}
    };

    for (const auto& offset : offsets) {
        int adjX = cx + offset[0];
        int adjY = cy + offset[1];
        if (adjX >= 0 && adjX < 128 && adjY >= 0 && adjY < 128) {
            if (this->isMapCellLand(adjX, adjY, info)) {
                count++;
            }
        }
    }
    return count;
}

bool UsrAI::isPositionReachable(int x, int y, const tagInfo& info) {
    const int offsets[8][2] = {
        {-1, 0}, {1, 0}, {0, -1}, {0, 1},
        {-1, -1}, {-1, 1}, {1, -1}, {1, 1}
    };

    for (const auto& offset : offsets) {
        int checkX = x + offset[0];
        int checkY = y + offset[1];

        if (checkX >= 0 && checkY >= 0 && checkX < 128 && checkY < 128) {
            if (this->isLand((*info.theMap)[checkX][checkY].type) &&
                !occupiedPositions.count({checkX, checkY})) {
                return true;
            }
        }
    }
    return false;
}

bool UsrAI::isTooCloseToExistingDocks(int newDockX, int newDockY, const tagInfo& info) {
    const int MIN_DOCK_SEPARATION_EDGE_TO_EDGE = 10;
    const int DOCK_SIZE = 2;
    const int MAX_COORD_DIFF_FOR_CLOSENESS = DOCK_SIZE + MIN_DOCK_SEPARATION_EDGE_TO_EDGE;

    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_DOCK && b.Percent == 100) {
            int existingDockX = b.BlockDR;
            int existingDockY = b.BlockUR;

            int diffX = abs(newDockX - existingDockX);
            int diffY = abs(newDockY - existingDockY);

            if (diffX < MAX_COORD_DIFF_FOR_CLOSENESS && diffY < MAX_COORD_DIFF_FOR_CLOSENESS) {
                return true;
            }
        }
    }
    return false;
}

void UsrAI::initializeCenter(const tagInfo& info) {
    srand(time(NULL));

    for (const auto& building : info.buildings) {
        if (building.Type == BUILDING_CENTER) {
            center_x = building.BlockDR;
            center_y = building.BlockUR;
            centerInitialized = true;

            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    occupiedPositions.insert({center_x + i, center_y + j});
                }
            }

            currentStage = STAGE_BUILD_HOUSES;

            if (!dockPositionFound) {
                std::set<std::pair<int, int>> tempExcludedPositions;
                if (!fishPositionsInitialized) {
                    this->initializeFishPositions(info);
                }
                if (!fishPositions.empty() && this->findDockPositionNearFish(foundDockX, foundDockY, fishPositions[0], info, tempExcludedPositions)) {
                    dockPositionFound = true;
                }
            }

            if (!info.farmers.empty()) {
                houseBuilderSN = info.farmers[0].SN;
                for (size_t i = 0; i < info.farmers.size(); i++) {
                    if (info.farmers[i].SN != houseBuilderSN) {
                        ordinaryVillagers.insert(info.farmers[i].SN);
                    }
                }
            }
            break;
        }
    }
}

bool UsrAI::isPositionValidForBuilding(int x, int y, int width, int height, int buildingType, const tagInfo& info) {
    int firstHeight = -2;

    if (buildingType == BUILDING_DOCK) {
        if (width != 2 || height != 2) {
            return false;
        }

        if (!(this->isOcean((*info.theMap)[x][y].type) &&
              this->isOcean((*info.theMap)[x + 1][y].type) &&
              this->isOcean((*info.theMap)[x][y + 1].type) &&
              this->isOcean((*info.theMap)[x + 1][y + 1].type))) {
            return false;
        }

        bool hasFullSideAdjacentToLand = false;
        if (x - 1 >= 0 &&
            this->isMapCellLand(x - 1, y, info) &&
            this->isMapCellLand(x - 1, y + 1, info)) {
            hasFullSideAdjacentToLand = true;
        }
        if (!hasFullSideAdjacentToLand && x + 2 < 128 &&
            this->isMapCellLand(x + 2, y, info) &&
            this->isMapCellLand(x + 2, y + 1, info)) {
            hasFullSideAdjacentToLand = true;
        }
        if (!hasFullSideAdjacentToLand && y - 1 >= 0 &&
            this->isMapCellLand(x, y - 1, info) &&
            this->isMapCellLand(x + 1, y - 1, info)) {
            hasFullSideAdjacentToLand = true;
        }
        if (!hasFullSideAdjacentToLand && y + 2 < 128 &&
            this->isMapCellLand(x, y + 2, info) &&
            this->isMapCellLand(x + 1, y + 2, info)) {
            hasFullSideAdjacentToLand = true;
        }

        if (!hasFullSideAdjacentToLand) {
            return false;
        }

        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                if (occupiedPositions.count({x + i, y + j})) {
                    return false;
                }
            }
        }

        return true;
    }

    for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
            int checkX = x + i;
            int checkY = y + j;

            if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128) {
                return false;
            }

            if (!this->isLand((*info.theMap)[checkX][checkY].type) || (*info.theMap)[checkX][checkY].height == -1) {
                return false;
            }

            if (firstHeight == -2) {
                firstHeight = (*info.theMap)[checkX][checkY].height;
            } else if ((*info.theMap)[checkX][checkY].height != firstHeight) {
                return false;
            }

            if (occupiedPositions.count({checkX, checkY})) {
                return false;
            }

            for (const auto& b : info.buildings) {
                int b_width, b_height;
                if (b.Type == BUILDING_DOCK) { b_width = 2; b_height = 2; }
                else if (b.Type == BUILDING_STOCK || b.Type == BUILDING_CENTER || b.Type == BUILDING_GRANARY ||
                         b.Type == BUILDING_ARMYCAMP || b.Type == BUILDING_MARKET || b.Type == BUILDING_FARM ||
                         b.Type == BUILDING_RANGE || b.Type == BUILDING_STABLE) { b_width = 3; b_height = 3; }
                else if (b.Type == BUILDING_HOME || b.Type == BUILDING_ARROWTOWER) { b_width = 2; b_height = 2; }
                else { b_width = 1; b_height = 1; }

                if (checkX >= b.BlockDR && checkX < (b.BlockDR + b_width) &&
                    checkY >= b.BlockUR && checkY < (b.BlockUR + b_height)) {
                    return false;
                }
            }

            for (const auto& res : info.resources) {
                if (res.BlockDR == checkX && res.BlockUR == checkY) {
                    return false;
                }
            }
        }
    }

    const int MIN_DISTANCE_FROM_OCEAN = 2;

    for (int dx = -MIN_DISTANCE_FROM_OCEAN; dx <= width + MIN_DISTANCE_FROM_OCEAN - 1; dx++) {
        for (int dy = -MIN_DISTANCE_FROM_OCEAN; dy <= height + MIN_DISTANCE_FROM_OCEAN - 1; dy++) {
            int checkX = x + dx;
            int checkY = y + dy;

            if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                    return false;
                }
            }
        }
    }

    if (buildingType == BUILDING_HOME) {
        for (int i = x - 1; i <= x + 2; ++i) {
            for (int j = y - 1; j <= y + 2; ++j) {
                for (const auto& b : info.buildings) {
                    if (b.Type == BUILDING_HOME) {
                        if (i >= b.BlockDR && i < b.BlockDR + 2 &&
                            j >= b.BlockUR && j < b.BlockUR + 2) {
                            return false;
                        }
                    }
                }
            }
        }
    }

    return true;
}

void UsrAI::afterUpgradePhase(const tagInfo& info) {
    if (!toolAgeInitialized) {
        initializeToolAge(info);
    }

    int currentWarshipCount = 0;
    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) {
            currentWarshipCount++;
        }
    }

    if (currentWarshipCount >= TARGET_WARSHIPS) {

        if (toolAgeBuilderSN != -1) {
            ordinaryVillagers.insert(toolAgeBuilderSN);
            toolAgeBuilderSN = -1;
            toolAgeBuilderAssigned = false;
            toolAgeBuilderBusy = false;
        }

        toolAgeInitialized = false;
        warshipProductionTriggered = false;
        currentStage = STAGE_EXPLORE;
        return;
    }

    if (warshipProductionTriggered) {
        static int warshipProductionCounter = 0;
        warshipProductionCounter++;

        if (warshipProductionCounter % 10 == 0) {
            if (currentWarshipCount < TARGET_WARSHIPS) {
                for (const auto& building : info.buildings) {
                    if (building.Type == BUILDING_DOCK && building.Percent == 100 && building.Project == 0) {
                        int warshipsProducedByThisDock = dockWarshipCount[building.SN];
                        if (warshipsProducedByThisDock < TARGET_WARSHIPS_PER_DOCK) {
                            if (info.Wood >= BUILDING_DOCK_CREATE_SHIP_WOOD + 150) {
                                int ret = BuildingAction(building.SN, BUILDING_DOCK_CREATE_SHIP);
                                if (ret > 0) {
                                    dockWarshipCount[building.SN]++;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    handleToolAgeConstruction(info);

    if (villagersProducedAfterUpgrade < villagersToProduceAfterUpgrade) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_CENTER && building.Percent == 100 && building.Project == 0) {
                if (info.Meat >= BUILDING_CENTER_CREATEFARMER_FOOD &&
                    (info.farmers.size() + info.armies.size()) < info.Human_MaxNum) {
                    int ret = BuildingAction(building.SN, BUILDING_CENTER_CREATEFARMER);
                    if (ret > 0) {
                        villagersProducedAfterUpgrade++;
                    }
                    return;
                }
            }
        }
    }

    this->assignTasksToVillagersWithLimits(info, false);
    this->assignFishingBoatsToFishResources(info);

    if (checkToolAgeCompletion(info)) {
        if (toolAgeBuilderSN != -1) {
            ordinaryVillagers.insert(toolAgeBuilderSN);
            toolAgeBuilderSN = -1;
            toolAgeBuilderAssigned = false;
            toolAgeBuilderBusy = false;
        }

        toolAgeInitialized = false;
        warshipProductionTriggered = false;

        currentStage = STAGE_BUILD_WARSHIPS;
    }
}

bool UsrAI::isPositionValidForHouse(int x, int y, const tagInfo& info) {
    return this->isPositionValidForBuilding(x, y, 2, 2, BUILDING_HOME, info);
}

bool UsrAI::findCoastalPositionNearCenter(int& x, int& y, const tagInfo& info, const std::set<std::pair<int, int>>& excludedPositions) {
    const int MAX_RADIUS = 8;

    for (int r = 1; r <= MAX_RADIUS; r++) {
        for (int i = -r; i <= r; ++i) {
            for (int j = -r; j <= r; ++j) {
                if (abs(i) != r && abs(j) != r) continue;

                int checkX = center_x + i;
                int checkY = center_y + j;

                if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128) {
                    continue;
                }

                if (excludedPositions.count({checkX, checkY})) {
                    continue;
                }

                if (this->isPositionValidForBuilding(checkX, checkY, 2, 2, BUILDING_DOCK, info)) {
                    if (this->isPositionReachable(checkX, checkY, info)) {
                        x = checkX;
                        y = checkY;
                        return true;
                    }
                }
            }
        }
    }
    return false;
}

void UsrAI::initializeFishPositions(const tagInfo& info) {
    for (const auto& res : info.resources) {
        if (res.Type == RESOURCE_FISH) {
            fishPositions.push_back({res.BlockDR, res.BlockUR});
        }
    }
    std::sort(fishPositions.begin(), fishPositions.end(), [&](const std::pair<int, int>& a, const std::pair<int, int>& b) {
        int distA = abs(a.first - center_x) + abs(a.second - center_y);
        int distB = abs(b.first - center_x) + abs(b.second - center_y);
        return distA < distB;
    });
    fishPositionsInitialized = true;
}

bool UsrAI::isDockNearFish(const std::pair<int, int>& fishPos, const tagInfo& info) {
    const int DOCK_NEAR_FISH_RADIUS = 5;
    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_DOCK) {
            int minDist = INT_MAX;
            for (int i = 0; i < 2; ++i) {
                for (int j = 0; j < 2; ++j) {
                    int dockCornerX = b.BlockDR + i;
                    int dockCornerY = b.BlockUR + j;
                    int dist = abs(dockCornerX - fishPos.first) + abs(dockCornerY - fishPos.second);
                    if (dist < minDist) {
                        minDist = dist;
                    }
                }
            }
            if (minDist <= DOCK_NEAR_FISH_RADIUS) {
                return true;
            }
        }
    }
    return false;
}

bool UsrAI::findDockPositionNearFish(int& x, int& y, const std::pair<int, int>& targetFishPos, const tagInfo& info, const std::set<std::pair<int, int>>& excludedPositions) {
    const int SEARCH_RADIUS_AROUND_FISH_FOR_DOCK = 8;

    int fishX = targetFishPos.first;
    int fishY = targetFishPos.second;

    int bestDockX = -1, bestDockY = -1;
    double maxConnectionScore = -1.0;

    for (int dx_dock = -SEARCH_RADIUS_AROUND_FISH_FOR_DOCK; dx_dock <= SEARCH_RADIUS_AROUND_FISH_FOR_DOCK; ++dx_dock) {
        for (int dy_dock = -SEARCH_RADIUS_AROUND_FISH_FOR_DOCK; dy_dock <= SEARCH_RADIUS_AROUND_FISH_FOR_DOCK; ++dy_dock) {
            int dockCandidateX = fishX + dx_dock;
            int dockCandidateY = fishY + dy_dock;

            if (excludedPositions.count({dockCandidateX, dockCandidateY})) {
                continue;
            }

            if (this->isTooCloseToExistingDocks(dockCandidateX, dockCandidateY, info)) {
                continue;
            }

            if (this->isPositionValidForBuilding(dockCandidateX, dockCandidateY, 2, 2, BUILDING_DOCK, info)) {
                if (this->isPositionReachable(dockCandidateX, dockCandidateY, info)) {
                    double currentConnectionScore = 0.0;
                    int numFullSidesAdjacent = 0;

                    if (dockCandidateX - 1 >= 0 &&
                        this->isMapCellLand(dockCandidateX - 1, dockCandidateY, info) &&
                        this->isMapCellLand(dockCandidateX - 1, dockCandidateY + 1, info)) {
                        numFullSidesAdjacent++;
                        currentConnectionScore += 100.0;
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX - 1, dockCandidateY, info);
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX - 1, dockCandidateY + 1, info);
                    }
                    if (dockCandidateX + 2 < 128 &&
                        this->isMapCellLand(dockCandidateX + 2, dockCandidateY, info) &&
                        this->isMapCellLand(dockCandidateX + 2, dockCandidateY + 1, info)) {
                        numFullSidesAdjacent++;
                        currentConnectionScore += 100.0;
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX + 2, dockCandidateY, info);
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX + 2, dockCandidateY + 1, info);
                    }
                    if (dockCandidateY - 1 >= 0 &&
                        this->isMapCellLand(dockCandidateX, dockCandidateY - 1, info) &&
                        this->isMapCellLand(dockCandidateX + 1, dockCandidateY - 1, info)) {
                        numFullSidesAdjacent++;
                        currentConnectionScore += 100.0;
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX, dockCandidateY - 1, info);
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX + 1, dockCandidateY - 1, info);
                    }
                    if (dockCandidateY + 2 < 128 &&
                        this->isMapCellLand(dockCandidateX, dockCandidateY + 2, info) &&
                        this->isMapCellLand(dockCandidateX + 1, dockCandidateY + 2, info)) {
                        numFullSidesAdjacent++;
                        currentConnectionScore += 100.0;
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX, dockCandidateY + 2, info);
                        currentConnectionScore += this->countAdjacentLand(dockCandidateX + 1, dockCandidateY + 2, info);
                    }

                    currentConnectionScore += numFullSidesAdjacent * 500.0;

                    if (currentConnectionScore > maxConnectionScore) {
                        maxConnectionScore = currentConnectionScore;
                        bestDockX = dockCandidateX;
                        bestDockY = dockCandidateY;
                    }
                }
            }
        }
    }

    if (bestDockX != -1) {
        x = bestDockX;
        y = bestDockY;
        return true;
    }

    return false;
}

void UsrAI::assignTasksToVillagersWithLimits(const tagInfo& info, bool reserveOneIdleForDock) {
    for (auto it = ordinaryVillagers.begin(); it != ordinaryVillagers.end(); ) {
        bool exists = false;
        for (const auto& farmer : info.farmers) {
            if (farmer.SN == *it) {
                exists = true;
                break;
            }
        }
        if (!exists) {
            it = ordinaryVillagers.erase(it);
        }
        else {
            ++it;
        }
    }

    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort != 0) continue;

        if ((farmer.SN == houseBuilderSN && !dockBuilderReserved && currentStage == STAGE_BUILD_HOUSES) ||
            (farmer.SN == dockBuilderSN && dockBuilderReserved)) {
            continue;
        }
        if (currentStage == STAGE_AFTER_UPGRADE && toolAgeBuilderAssigned && farmer.SN == toolAgeBuilderSN) {
            continue;
        }
        if (upgradeStarted && farmer.SN == upgradeBuilderSN) {
            continue;
        }

        if (ordinaryVillagers.find(farmer.SN) == ordinaryVillagers.end()) {
            ordinaryVillagers.insert(farmer.SN);
        }
    }

    int woodWorkers = 0;
    int foodWorkers = 0;
    int buildWorkers = 0;
    int idleCount = 0;
    int walkingCount = 0;

    for (const auto& farmer : info.farmers) {
        if (currentStage == STAGE_AFTER_UPGRADE && toolAgeBuilderAssigned && farmer.SN == toolAgeBuilderSN) {
            continue;
        }
        if (upgradeStarted && farmer.SN == upgradeBuilderSN) {
            continue;
        }

        if (ordinaryVillagers.count(farmer.SN) == 0) {
            continue;
        }

        if (farmer.NowState == HUMAN_STATE_IDLE) {
            idleCount++;
        } else if (farmer.NowState == HUMAN_STATE_WALKING) {
            walkingCount++;
        } else if (farmer.NowState == HUMAN_STATE_WORKING) {
            for (const auto& res : info.resources) {
                if (res.SN == farmer.WorkObjectSN) {
                    if (res.Type == RESOURCE_TREE) {
                        woodWorkers++;
                    } else if (res.Type == RESOURCE_GAZELLE ||
                               res.Type == RESOURCE_ELEPHANT ||
                               res.Type == RESOURCE_FISH) {
                        foodWorkers++;
                    }
                    break;
                }
            }
        }
    }

    std::vector<const tagFarmer*> availableFarmers;
    for (const auto& farmer : info.farmers) {
        if (currentStage == STAGE_AFTER_UPGRADE && toolAgeBuilderAssigned && farmer.SN == toolAgeBuilderSN) {
            continue;
        }
        if (upgradeStarted && farmer.SN == upgradeBuilderSN) {
            continue;
        }

        if (ordinaryVillagers.count(farmer.SN)) {
            if (farmer.NowState == HUMAN_STATE_IDLE) {
                availableFarmers.push_back(&farmer);
            }
            else if (farmer.NowState == HUMAN_STATE_WALKING && farmer.WorkObjectSN == 0) {
                int distFromCenter = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
                if (distFromCenter <= 4) {
                    availableFarmers.push_back(&farmer);
                }
            }
        }
    }

    std::sort(availableFarmers.begin(), availableFarmers.end(), [&](const tagFarmer* a, const tagFarmer* b) {
        int distA = abs(a->BlockDR - center_x) + abs(a->BlockUR - center_y);
        int distB = abs(b->BlockDR - center_x) + abs(b->BlockUR - center_y);
        return distA < distB;
    });

    for (const tagFarmer* farmer_ptr : availableFarmers) {
        const tagFarmer& current_farmer = *farmer_ptr;
        bool assignedThisTurn = false;
        std::unordered_set<int> villagerExcludedResources;

        if (currentStage != STAGE_AFTER_UPGRADE &&
            !upgradeStarted &&
            foodWorkers < 2)
        {
            int targetFoodSN = -1;

            targetFoodSN = this->findNearestResource(current_farmer, RESOURCE_GAZELLE, info, villagerExcludedResources);
            if (targetFoodSN == -1) targetFoodSN = this->findNearestResource(current_farmer, RESOURCE_ELEPHANT, info, villagerExcludedResources);
            if (targetFoodSN == -1) targetFoodSN = this->findNearestResource(current_farmer, RESOURCE_FISH, info, villagerExcludedResources);

            if (targetFoodSN != -1) {
                int ret = HumanAction(farmer_ptr->SN, targetFoodSN);
                if (ret > 0) {
                    foodWorkers++;
                    assignedThisTurn = true;
                } else {
                    villagerExcludedResources.insert(targetFoodSN);
                }
            }
        }

        if (!assignedThisTurn) {
            int attempts = 0;
            while (!assignedThisTurn && attempts < 5) {
                int targetTreeSN = this->findNearestResource(current_farmer, RESOURCE_TREE, info, villagerExcludedResources);
                if (targetTreeSN != -1) {
                    int ret = HumanAction(farmer_ptr->SN, targetTreeSN);
                    if (ret > 0) {
                        woodWorkers++;
                        assignedThisTurn = true;
                    } else {
                        villagerExcludedResources.insert(targetTreeSN);
                        attempts++;
                    }
                } else {
                    break;
                }
            }
        }
    }
}

int UsrAI::findNearestResource(const tagFarmer& farmer, int resourceType, const tagInfo& info, const std::unordered_set<int>& excludedSNs) {
    int nearestSN = -1;
    double minDistance = -1;

    for (const auto& res : info.resources) {
        if (res.Type == resourceType && res.Cnt > 0 && excludedSNs.find(res.SN) == excludedSNs.end()) {
            double distance = abs(farmer.BlockDR - res.BlockDR) + abs(farmer.BlockUR - res.BlockUR);
            if (nearestSN == -1 || distance < minDistance) {
                minDistance = distance;
                nearestSN = res.SN;
            }
        }
    }
    return nearestSN;
}

void UsrAI::produceVillagers(const tagInfo& info) {
    for (const auto& building : info.buildings) {
        if (building.Type == BUILDING_CENTER && building.Percent == 100 && building.Project == 0) {
            if (info.Meat >= 50) {
                if (info.farmers.size() + info.armies.size() < info.Human_MaxNum) {
                    int ret = BuildingAction(building.SN, BUILDING_CENTER_CREATEFARMER);
                    if (ret > 0) {
                        lastVillagerProductionTime = time(nullptr);
                    }
                }
            }
            break;
        }
    }
}

bool UsrAI::findNearbyPosition(int& x, int& y, const tagInfo& info, int width, int height, int buildingType) {
    int startX = center_x;
    int startY = center_y;

    const int MIN_START_RADIUS = 3;

    for (int r = MIN_START_RADIUS; r <= MAX_HOUSE_SEARCH_RADIUS; ++r) {
        for (int i = -r; i <= r; ++i) {
            for (int j = -r; j <= r; ++j) {
                if (r > MIN_START_RADIUS && abs(i) != r && abs(j) != r) continue;

                int checkX = startX + i;
                int checkY = startY + j;

                if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128)
                    continue;

                if (this->isPositionValidForBuilding(checkX, checkY, width, height, buildingType, info)) {
                    x = checkX;
                    y = checkY;
                    lastHouseX = x;
                    lastHouseY = y;
                    return true;
                }
            }
        }
    }

    return false;
}

int UsrAI::getDistanceToNearestOcean(int x, int y, const tagInfo& info) {
    int minDist = 999;

    const int searchRadius = 10;
    for (int dx = -searchRadius; dx <= searchRadius; dx++) {
        for (int dy = -searchRadius; dy <= searchRadius; dy++) {
            int checkX = x + dx;
            int checkY = y + dy;

            if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                    int dist = abs(dx) + abs(dy);
                    if (dist < minDist) {
                        minDist = dist;
                    }
                }
            }
        }
    }

    return minDist;
}

bool UsrAI::findBestStockPosition(int& x, int& y, const tagInfo& info) {
    int bestX = -1, bestY = -1;
    int maxTreeCount = -1;
    const int searchRadius = 10;

    std::vector<std::pair<int, int>> treePositions;
    for (const auto& res : info.resources) {
        if (res.Type == RESOURCE_TREE && res.Cnt > 0) {
            treePositions.push_back({res.BlockDR, res.BlockUR});
        }
    }

    for (int dx = -searchRadius; dx <= searchRadius; dx++) {
        for (int dy = -searchRadius; dy <= searchRadius; dy++) {
            int candidateX = center_x + dx;
            int candidateY = center_y + dy;

            if (candidateX < 0 || candidateY < 0 || candidateX >= 128 || candidateY >= 128) {
                continue;
            }

            if (isPositionValidForBuilding(candidateX, candidateY, 3, 3, BUILDING_STOCK, info)) {
                bool tooCloseToOcean = false;
                const int SAFE_DISTANCE = 3;

                for (int checkX = candidateX - SAFE_DISTANCE;
                     checkX <= candidateX + 3 + SAFE_DISTANCE; checkX++) {
                    for (int checkY = candidateY - SAFE_DISTANCE;
                         checkY <= candidateY + 3 + SAFE_DISTANCE; checkY++) {
                        if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                            if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                                tooCloseToOcean = true;
                                break;
                            }
                        }
                    }
                    if (tooCloseToOcean) break;
                }

                if (tooCloseToOcean) {
                    continue;
                }

                int treeCount = 0;
                for (const auto& tree : treePositions) {
                    double distance = sqrt(pow(candidateX - tree.first, 2) + pow(candidateY - tree.second, 2));
                    if (distance <= 5.0) {
                        treeCount++;
                    }
                }

                if (treeCount > maxTreeCount) {
                    maxTreeCount = treeCount;
                    bestX = candidateX;
                    bestY = candidateY;
                }
            }
        }
    }

    if (bestX != -1 && bestY != -1) {
        x = bestX;
        y = bestY;
        return true;
    }

    return false;
}

void UsrAI::collectResourcesPhase(const tagInfo& info) {
    if (!fishPositionsInitialized) {
        this->initializeFishPositions(info);
    }

    this->assignTasksToVillagersWithLimits(info, !dockBuilt);
    this->assignFishingBoatsToFishResources(info);
}

void UsrAI::populationGrowthPhase(const tagInfo& info) {
    int currentPopulation = info.farmers.size() + info.armies.size();
    int populationCapacity = info.Human_MaxNum;

    this->produceVillagers(info);

    if (currentPopulation >= targetPopulation && houseCount == TARGET_HOUSES && housesUnderConstruction == 0) {
        currentStage = STAGE_BUILD_REQUIRED_BUILDINGS;

        if (houseBuilderSN != -1 && dockBuilderSN == -1) {
            dockBuilderSN = houseBuilderSN;
            dockBuilderReserved = true;
            if (ordinaryVillagers.count(dockBuilderSN)) {
                ordinaryVillagers.erase(dockBuilderSN);
            }
        }
        return;
    }

    this->assignTasksToVillagersWithLimits(info, !dockBuilt);
    this->assignFishingBoatsToFishResources(info);
}

void UsrAI::buildRequiredBuildingsPhase(const tagInfo& info) {
    // 更新成功建造的船坞数量
    completedDocksCount = 0;
    int docksUnderConstruction = 0;
    successfulDockPositions.clear();

    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_DOCK) {
            if (b.Percent == 100) {
                completedDocksCount++;
                successfulDockPositions[{b.BlockDR, b.BlockUR}] = 1;
            } else if (b.Percent < 100) {
                docksUnderConstruction++;
            }
        }
    }

    // 如果达到目标数量，进入下一阶段
    if (completedDocksCount >= TARGET_DOCKS_NUM) {
        currentStage = STAGE_BUILD_FISHING_BOAT;
        if (dockBuilderSN != -1 && ordinaryVillagers.find(dockBuilderSN) == ordinaryVillagers.end()) {
            ordinaryVillagers.insert(dockBuilderSN);
            dockBuilderReserved = false;
        }
        // 清理重试记录
        failedDockPositions.clear();
        attemptedFishPositions.clear();
        DebugText("已完成 " + std::to_string(completedDocksCount) + " 个船坞，进入下一阶段");
        return;
    }

    // 检查是否需要等待冷却
    if (dockBuildAttemptFrame > 0 && (info.GameFrame - dockBuildAttemptFrame) < dockBuildCooldown) {
        // 冷却期间仍然分配其他任务
        this->assignTasksToVillagersWithLimits(info, false);
        return;
    }

    // 尝试建造新的船坞
    if (completedDocksCount + docksUnderConstruction < TARGET_DOCKS_NUM) {
        if (attemptBuildDock(info)) {
            dockBuildAttemptFrame = info.GameFrame;
            DebugText("尝试建造第 " + std::to_string(completedDocksCount + docksUnderConstruction + 1) + " 个船坞");
        } else {
            // 如果所有位置都失败了，尝试清理失败记录重新开始
            if (info.GameFrame - dockBuildAttemptFrame > 100) { // 100帧后重置
                DebugText("重置船坞建造失败记录");
                failedDockPositions.clear();
                attemptedFishPositions.clear();
                dockBuildAttemptFrame = info.GameFrame;
            }
        }
    }

    // 建造储存建筑
    if (!stockBuilt && completedDocksCount >= 1) {
        attemptBuildStock(info);
    }

    this->assignTasksToVillagersWithLimits(info, false);
}

bool UsrAI::attemptBuildDock(const tagInfo& info) {
    // 检查资源
    if (info.Wood < BUILD_DOCK_WOOD) {
        DebugText("木材不足，需要 " + std::to_string(BUILD_DOCK_WOOD) + "，当前 " + std::to_string(info.Wood));
        return false;
    }

    // 获取或分配建造者
    tagFarmer* builderFarmer = nullptr;
    if (!ensureDockBuilder(info, builderFarmer)) {
        DebugText("无法获取船坞建造者");
        return false;
    }

    // 初始化鱼资源位置
    if (!fishPositionsInitialized) {
        initializeFishPositions(info);
    }

    // 尝试在每个鱼资源附近建造
    for (const auto& fishPos : fishPositions) {
        // 跳过已经尝试过的鱼资源
        bool alreadyAttempted = false;
        for (const auto& attempted : attemptedFishPositions) {
            if (attempted.first == fishPos.first && attempted.second == fishPos.second) {
                alreadyAttempted = true;
                break;
            }
        }

        if (alreadyAttempted) {
            continue;
        }

        // 检查是否已有船坞在此鱼资源附近
        if (isDockNearFish(fishPos, info)) {
            attemptedFishPositions.push_back(fishPos);
            continue;
        }

        // 尝试找到建造位置
        std::vector<std::pair<int, int>> candidatePositions;
        if (findAllDockPositionsNearFish(candidatePositions, fishPos, info)) {
            // 尝试每个候选位置
            for (const auto& pos : candidatePositions) {
                // 检查是否已经失败太多次
                if (failedDockPositions[pos] >= maxDockRetries) {
                    DebugText("位置 (" + std::to_string(pos.first) + "," +
                             std::to_string(pos.second) + ") 失败次数过多，跳过");
                    continue;
                }

                // 再次验证位置有效性
                if (!isPositionValidForBuilding(pos.first, pos.second, 2, 2, BUILDING_DOCK, info)) {
                    DebugText("位置 (" + std::to_string(pos.first) + "," +
                             std::to_string(pos.second) + ") 验证失败");
                    failedDockPositions[pos]++;
                    continue;
                }

                // 尝试建造
                DebugText("尝试在 (" + std::to_string(pos.first) + "," +
                         std::to_string(pos.second) + ") 建造船坞");

                int ret = HumanBuild(builderFarmer->SN, BUILDING_DOCK, pos.first, pos.second);

                if (ret > 0) {
                    DebugText("船坞建造命令成功，ID: " + std::to_string(ret));
                    dockConstructionStarted = true;
                    // 标记位置为已占用
                    for (int i = 0; i < 2; i++) {
                        for (int j = 0; j < 2; j++) {
                            occupiedPositions.insert({pos.first + i, pos.second + j});
                        }
                    }
                    // 记录已尝试的鱼资源
                    attemptedFishPositions.push_back(fishPos);
                    return true;
                } else {
                    // 记录失败
                    failedDockPositions[pos]++;
                    logBuildError(ret, pos.first, pos.second);

                    // 如果是距离问题，可能需要移动建造者
                    if (ret == ACTION_INVALID_DISTANCE_FAR) {
                        moveBuilderCloser(builderFarmer, pos.first, pos.second);
                    }
                }
            }
        }
    }

    // 如果所有鱼资源都尝试过了，尝试在海岸任意位置建造
    if (attemptedFishPositions.size() >= fishPositions.size()) {
        DebugText("所有鱼资源位置都已尝试，寻找其他海岸位置");
        return attemptBuildDockAnywhere(info, builderFarmer);
    }

    return false;
}

bool UsrAI::ensureDockBuilder(const tagInfo& info, tagFarmer*& builderFarmer) {
    // 检查现有建造者是否有效
    if (dockBuilderSN != -1) {
        for (const auto& farmer : info.farmers) {
            if (farmer.SN == dockBuilderSN && farmer.FarmerSort == 0) {
                if (farmer.NowState == HUMAN_STATE_IDLE ||
                    (farmer.NowState == HUMAN_STATE_WALKING && farmer.WorkObjectSN == 0)) {
                    builderFarmer = const_cast<tagFarmer*>(&farmer);
                    return true;
                }
                // 建造者忙碌
                return false;
            }
        }
        // 建造者不存在，重置
        DebugText("船坞建造者 " + std::to_string(dockBuilderSN) + " 不存在，重新分配");
        dockBuilderSN = -1;
        dockBuilderReserved = false;
    }


    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 0 && farmer.NowState == HUMAN_STATE_IDLE) {

            if (farmer.SN == houseBuilderSN || farmer.SN == toolAgeBuilderSN) {
                continue;
            }

            builderFarmer = const_cast<tagFarmer*>(&farmer);
            dockBuilderSN = farmer.SN;
            dockBuilderReserved = true;
            ordinaryVillagers.erase(dockBuilderSN);
            DebugText("分配新的船坞建造者: " + std::to_string(dockBuilderSN));
            return true;
        }
    }

    return false;
}

bool UsrAI::findAllDockPositionsNearFish(std::vector<std::pair<int, int>>& positions,
                                         const std::pair<int, int>& fishPos,
                                         const tagInfo& info) {
    positions.clear();
    const int SEARCH_RADIUS = 10;

    struct PositionScore {
        std::pair<int, int> pos;
        double score;
    };
    std::vector<PositionScore> scoredPositions;

    for (int dx = -SEARCH_RADIUS; dx <= SEARCH_RADIUS; dx++) {
        for (int dy = -SEARCH_RADIUS; dy <= SEARCH_RADIUS; dy++) {
            int x = fishPos.first + dx;
            int y = fishPos.second + dy;

            if (x < 0 || y < 0 || x >= 127 || y >= 127) continue;

            auto pos = std::make_pair(x, y);
            if (failedDockPositions[pos] >= maxDockRetries) continue;

            if (isTooCloseToExistingDocks(x, y, info)) continue;

            if (isPositionValidForBuilding(x, y, 2, 2, BUILDING_DOCK, info)) {
                if (isPositionReachable(x, y, info)) {
                    double score = calculateDockPositionScore(x, y, fishPos, info);
                    scoredPositions.push_back({pos, score});
                }
            }
        }
    }

    std::sort(scoredPositions.begin(), scoredPositions.end(),
              [](const PositionScore& a, const PositionScore& b) {
                  return a.score > b.score;
              });

    for (size_t i = 0; i < std::min(size_t(5), scoredPositions.size()); i++) {
        positions.push_back(scoredPositions[i].pos);
    }

    return !positions.empty();
}

double UsrAI::calculateDockPositionScore(int x, int y,
                                         const std::pair<int, int>& fishPos,
                                         const tagInfo& info) {
    double score = 0.0;

    double distToFish = sqrt(pow(x - fishPos.first, 2) + pow(y - fishPos.second, 2));
    score += (20.0 - distToFish) * 10;

    int landConnections = countAdjacentLand(x, y, info) +
                         countAdjacentLand(x+1, y, info) +
                         countAdjacentLand(x, y+1, info) +
                         countAdjacentLand(x+1, y+1, info);
    score += landConnections * 5;

    double distToCenter = sqrt(pow(x - center_x, 2) + pow(y - center_y, 2));
    if (distToCenter < 10) {
        score += 30;
    } else if (distToCenter < 20) {
        score += 20;
    }

    return score;
}

void UsrAI::logBuildError(int errorCode, int x, int y) {
    std::string errorMsg = "船坞建造失败 at (" + std::to_string(x) + "," +
                          std::to_string(y) + ") 错误码: " + std::to_string(errorCode);

    switch(errorCode) {
        case ACTION_INVALID_HUMANBUILD_OVERLAP:
            errorMsg += " - 位置有重叠";
            break;
        case ACTION_INVALID_POSITION_NOT_FIT:
            errorMsg += " - 位置不合适";
            break;
        case ACTION_INVALID_DISTANCE_FAR:
            errorMsg += " - 距离太远";
            break;
        case ACTION_INVALID_HUMANBUILD_UNEXPLORE:
            errorMsg += " - 位置未探索";
            break;
        case ACTION_INVALID_RESOURCE:
            errorMsg += " - 资源不足";
            break;
        case ACTION_INVALID_HUMANBUILD_DIFFERENTHIGH:
            errorMsg += " - 高度不一致";
            break;
    }

    DebugText(errorMsg);
}

void UsrAI::moveBuilderCloser(tagFarmer* builder, int targetX, int targetY) {
    if (!builder) return;

    int bestX = -1, bestY = -1;
    double minDist = 999999;

    for (int dx = -3; dx <= 3; dx++) {
        for (int dy = -3; dy <= 3; dy++) {
            int x = targetX + dx;
            int y = targetY + dy;

            if (x >= 0 && x < 128 && y >= 0 && y < 128) {
                if (isMapCellLand(x, y, getInfo())) {
                    double dist = sqrt(pow(x - builder->BlockDR, 2) +
                                     pow(y - builder->BlockUR, 2));
                    if (dist < minDist) {
                        minDist = dist;
                        bestX = x;
                        bestY = y;
                    }
                }
            }
        }
    }

    if (bestX != -1 && bestY != -1) {
        HumanMove(builder->SN, bestX * BLOCKSIDELENGTH, bestY * BLOCKSIDELENGTH);
    }
}

bool UsrAI::attemptBuildDockAnywhere(const tagInfo& info, tagFarmer* builder) {
    for (int radius = 5; radius <= 30; radius += 5) {
        for (int angle = 0; angle < 360; angle += 15) {
            double rad = angle * 3.14159 / 180.0;
            int x = center_x + (int)(radius * cos(rad));
            int y = center_y + (int)(radius * sin(rad));

            if (x < 0 || y < 0 || x >= 127 || y >= 127) continue;

            auto pos = std::make_pair(x, y);
            if (failedDockPositions[pos] >= maxDockRetries) continue;

            if (!isTooCloseToExistingDocks(x, y, info) &&
                isPositionValidForBuilding(x, y, 2, 2, BUILDING_DOCK, info) &&
                isPositionReachable(x, y, info)) {

                int ret = HumanBuild(builder->SN, BUILDING_DOCK, x, y);
                if (ret > 0) {
                    for (int i = 0; i < 2; i++) {
                        for (int j = 0; j < 2; j++) {
                            occupiedPositions.insert({x + i, y + j});
                        }
                    }
                    return true;
                } else {
                    failedDockPositions[pos]++;
                }
            }
        }
    }

    return false;
}

void UsrAI::attemptBuildStock(const tagInfo& info) {
    int buildX, buildY;
    if (this->findBestStockPosition(buildX, buildY, info)) {
        if (info.Wood >= BUILD_STOCK_WOOD) {
            tagFarmer* builderForStock = nullptr;
            for (const auto& farmer : info.farmers) {
                if (ordinaryVillagers.count(farmer.SN) &&
                    farmer.NowState == HUMAN_STATE_IDLE &&
                    farmer.FarmerSort == 0) {
                    builderForStock = const_cast<tagFarmer*>(&farmer);
                    break;
                }
            }

            if (builderForStock != nullptr) {
                int ret = HumanBuild(builderForStock->SN, BUILDING_STOCK, buildX, buildY);
                if (ret > 0) {
                    for (int i = 0; i < 3; i++) {
                        for (int j = 0; j < 3; j++) {
                            occupiedPositions.insert({buildX+i, buildY+j});
                        }
                    }

                }
            }
        }
    }
}

void UsrAI::upgradeAgePhase(const tagInfo& info) {
    if (info.civilizationStage == CIVILIZATION_TOOLAGE) {
        ageUpgraded = true;
        currentStage = STAGE_AFTER_UPGRADE;
        villagersToProduceAfterUpgrade = 6;
        villagersProducedAfterUpgrade = 0;

        existingStocksAtUpgrade = 0;
        for (const auto& b : info.buildings) {
            if (b.Type == BUILDING_STOCK) {
                existingStocksAtUpgrade++;
            }
        }
        housesToBuildAfterUpgrade = TARGET_HOUSES + 4;
        return;
    }

    if (info.Meat >= 500) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_CENTER) {
                if (building.Percent == 100 && building.Project == 0) {
                    int ret = BuildingAction(building.SN, BUILDING_CENTER_UPGRADE);
                    if (ret > 0) {
                    }
                    break;
                }
            }
        }
    }

    this->assignTasksToVillagersWithLimits(info, false);
}

void UsrAI::initializeToolAge(const tagInfo& info) {
    if (toolAgeInitialized) return;
    toolAgeStocksBuilt = 0;
    toolAgeHousesBuilt = 0;
    granaryBuilt = false;
    marketBuilt = false;
    farmBuilt = false;
    farmsBuilt = 0;

    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_STOCK && b.Percent == 100) {
            toolAgeStocksBuilt++;
        }
        if (b.Type == BUILDING_HOME && b.Percent == 100) {
            toolAgeHousesBuilt++;
        }
        if (b.Type == BUILDING_GRANARY && b.Percent == 100) {
            granaryBuilt = true;
        }
        if (b.Type == BUILDING_MARKET && b.Percent == 100) {
            marketBuilt = true;
        }
        if (b.Type == BUILDING_FARM && b.Percent == 100) {
            farmsBuilt++;
            if (farmsBuilt > 0) farmBuilt = true;
        }
    }

    if (toolAgeStocksBuilt < TARGET_TOTAL_STOCKS) {
        toolAgePhase = 0;
    } else if (toolAgeHousesBuilt < TARGET_HOUSES + 4) {
        toolAgePhase = 1;
    } else if (!granaryBuilt || !marketBuilt) {
        toolAgePhase = 2;
    } else if (!woodCuttingUpgraded) {
        toolAgePhase = 3;
    } else if (farmsBuilt < TARGET_FARMS) {
        toolAgePhase = 4;
    } else {
        toolAgePhase = 5;
    }

    toolAgeInitialized = true;
    toolAgeBuilderSN = -1;
    toolAgeBuilderBusy = false;
}

bool UsrAI::assignToolAgeBuilder(const tagInfo& info) {
    if (toolAgeBuilderSN != -1) {
        bool builderExists = false;
        bool builderIdle = false;

        for (const auto& farmer : info.farmers) {
            if (farmer.SN == toolAgeBuilderSN && farmer.FarmerSort == 0) {
                builderExists = true;
                if (farmer.NowState == HUMAN_STATE_IDLE || farmer.NowState == HUMAN_STATE_WALKING) {
                    builderIdle = true;
                }
                break;
            }
        }

        if (builderExists && !builderIdle) {
            return false;
        }

        if (!builderExists) {
            toolAgeBuilderSN = -1;
            toolAgeBuilderBusy = false;
            toolAgeBuilderAssigned = false;
        } else if (builderIdle) {
            return true;
        }
    }

    if (toolAgeBuilderSN == -1) {
        std::vector<int> candidates;
        for (const auto& farmer : info.farmers) {
            if (farmer.FarmerSort == 0 &&
                (farmer.NowState == HUMAN_STATE_IDLE || farmer.NowState == HUMAN_STATE_WALKING)) {
                candidates.push_back(farmer.SN);
            }
        }

        if (!candidates.empty()) {
            for (int candidateSN : candidates) {
                if (ordinaryVillagers.find(candidateSN) == ordinaryVillagers.end()) {
                    toolAgeBuilderSN = candidateSN;
                    toolAgeBuilderBusy = false;
                    toolAgeBuilderAssigned = true;
                    return true;
                }
            }

            int selectedSN = candidates[0];
            toolAgeBuilderSN = selectedSN;
            ordinaryVillagers.erase(selectedSN);
            toolAgeBuilderBusy = false;
            toolAgeBuilderAssigned = true;
            return true;
        } else {
           ;
        }
    }

    return toolAgeBuilderSN != -1;
}

void UsrAI::handleToolAgeConstruction(const tagInfo& info) {

    if (!assignToolAgeBuilder(info)) {
        return;
    }

    checkToolAgeCompletion(info);

    if (toolAgeBuilderBusy) {
        return;
    }

    const tagFarmer* builder = nullptr;
    for (const auto& farmer : info.farmers) {
        if (farmer.SN == toolAgeBuilderSN) {
            builder = &farmer;
            break;
        }
    }

    if (!builder) {
        toolAgeBuilderSN = -1;
        toolAgeBuilderAssigned = false;
        return;
    }

    if (builder->NowState != HUMAN_STATE_IDLE) {
        return;
    }

    int buildX = -1, buildY = -1;
    int buildingType = -1;
    int requiredWood = 0;
    bool canBuild = false;

    switch (toolAgePhase) {
        case 0:
            if (toolAgeStocksBuilt < TARGET_TOTAL_STOCKS) {
                if (findBestStockPosition(buildX, buildY, info)) {
                    buildingType = BUILDING_STOCK;
                    requiredWood = BUILD_STOCK_WOOD;
                    canBuild = (info.Wood >= requiredWood);
                } else {
                    ;
                }
            }
            break;

        case 1:
            if (toolAgeHousesBuilt < TARGET_HOUSES + 4) {
                if (findNearbyPosition(buildX, buildY, info, 2, 2, BUILDING_HOME)) {
                    buildingType = BUILDING_HOME;
                    requiredWood = BUILD_HOUSE_WOOD;
                    canBuild = (info.Wood >= requiredWood);
                } else {
                    ;
                }
            }
            break;

        case 2:
            if (!granaryBuilt) {
                if (findNearbyPosition(buildX, buildY, info, 3, 3, BUILDING_GRANARY)) {
                    buildingType = BUILDING_GRANARY;
                    requiredWood = BUILD_GRANARY_WOOD;
                    canBuild = (info.Wood >= requiredWood);
                }
            } else if (!marketBuilt) {
                if (findNearbyPosition(buildX, buildY, info, 3, 3, BUILDING_MARKET)) {
                    buildingType = BUILDING_MARKET;
                    requiredWood = BUILD_MARKET_WOOD;
                    canBuild = (info.Wood >= requiredWood);
                }
            }
            break;

        case 3:
            if (!woodCuttingUpgraded) {
                for (const auto& building : info.buildings) {
                    if (building.Type == BUILDING_MARKET && building.Percent == 100 && building.Project == 0) {
                        if (info.Meat >= BUILDING_MARKET_WOOD_UPGRADE_FOOD &&
                            info.Wood >= BUILDING_MARKET_WOOD_UPGRADE_WOOD) {
                            int ret = BuildingAction(building.SN, BUILDING_MARKET_WOOD_UPGRADE);
                            if (ret > 0) {
                                woodCuttingUpgraded = true;
                                return;
                            }
                        } else {
                            ;
                        }
                        break;
                    }
                }
            }
            return;

        case 4:
            if (farmsBuilt < TARGET_FARMS) {
                if (findNearbyPosition(buildX, buildY, info, 3, 3, BUILDING_FARM)) {
                    buildingType = BUILDING_FARM;
                    requiredWood = BUILD_FARM_WOOD;
                    canBuild = (info.Wood >= requiredWood);
                } else {
                    ;
                }
            }
            break;
    }

    if (canBuild && buildX != -1 && buildY != -1 && buildingType != -1) {

        int ret = HumanBuild(toolAgeBuilderSN, buildingType, buildX, buildY);
        if (ret > 0) {
            toolAgeBuilderBusy = true;

            int size = (buildingType == BUILDING_HOME) ? 2 : 3;
            for (int i = 0; i < size; i++) {
                for (int j = 0; j < size; j++) {
                    occupiedPositions.insert({buildX + i, buildY + j});
                }
            }

            if (buildingType == BUILDING_FARM && !warshipProductionTriggered) {
                warshipProductionTriggered = true;
            }
        } else {
            ;
        }
    } else if (!canBuild && buildX != -1) {
        ;
    } else {
        ;
    }
}

bool UsrAI::checkToolAgeCompletion(const tagInfo& info) {
    int previousStocksBuilt = toolAgeStocksBuilt;
    int previousHousesBuilt = toolAgeHousesBuilt;
    bool previousGranaryBuilt = granaryBuilt;
    bool previousMarketBuilt = marketBuilt;
    int previousFarmsBuilt = farmsBuilt;

    toolAgeStocksBuilt = 0;
    toolAgeHousesBuilt = 0;
    granaryBuilt = false;
    marketBuilt = false;
    farmsBuilt = 0;

    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_STOCK && b.Percent == 100) {
            toolAgeStocksBuilt++;
        }
        if (b.Type == BUILDING_HOME && b.Percent == 100) {
            toolAgeHousesBuilt++;
        }
        if (b.Type == BUILDING_GRANARY && b.Percent == 100) {
            granaryBuilt = true;
        }
        if (b.Type == BUILDING_MARKET && b.Percent == 100) {
            marketBuilt = true;
        }
        if (b.Type == BUILDING_FARM && b.Percent == 100) {
            farmsBuilt++;
        }
    }

    bool shouldAdvancePhase = false;

    switch (toolAgePhase) {
        case 0:
            if (toolAgeStocksBuilt > previousStocksBuilt) {
               ;
            }
            if (toolAgeStocksBuilt >= TARGET_TOTAL_STOCKS) {
                toolAgePhase = 1;
                toolAgeBuilderBusy = false;
                shouldAdvancePhase = true;
            }
            break;

        case 1:
            if (toolAgeHousesBuilt > previousHousesBuilt) {
            }
            if (toolAgeHousesBuilt >= TARGET_HOUSES + 4) {
                toolAgePhase = 2;
                toolAgeBuilderBusy = false;
                shouldAdvancePhase = true;
            }
            break;

        case 2:
            if (granaryBuilt && !previousGranaryBuilt) {
                toolAgeBuilderBusy = false;
            }
            if (marketBuilt && !previousMarketBuilt) {
                toolAgeBuilderBusy = false;
            }
            if (granaryBuilt && marketBuilt) {
                toolAgePhase = 3;
                toolAgeBuilderBusy = false;
                shouldAdvancePhase = true;
            }
            break;

        case 3:
            if (woodCuttingUpgraded) {
                toolAgePhase = 4;
                toolAgeBuilderBusy = false;
                shouldAdvancePhase = true;
            }
            break;

        case 4:
            if (farmsBuilt > previousFarmsBuilt) {
                toolAgeBuilderBusy = false;
            }
            if (farmsBuilt >= TARGET_FARMS) {
                shouldAdvancePhase = true;
            }
            break;
    }

    if (shouldAdvancePhase) {
        ;
    }

    bool allComplete = (toolAgeStocksBuilt >= TARGET_TOTAL_STOCKS) &&
                      (toolAgeHousesBuilt >= TARGET_HOUSES + 4) &&
                      granaryBuilt && marketBuilt &&
                      woodCuttingUpgraded &&
                      (farmsBuilt >= TARGET_FARMS);

    if (allComplete) {
        if (toolAgeBuilderSN != -1) {
            ordinaryVillagers.insert(toolAgeBuilderSN);
            toolAgeBuilderSN = -1;
            toolAgeBuilderBusy = false;
            toolAgeBuilderAssigned = false;
        }

        return true;
    }

    return false;
}

void UsrAI::buildHousesPhase(const tagInfo& info) {
    if (houseCount >= 1) {
        this->produceVillagers(info);
    }

    if (houseCount == TARGET_HOUSES && housesUnderConstruction == 0) {
        if (completedDocksCount < TARGET_DOCKS_NUM && info.Wood >= BUILD_DOCK_WOOD) {
            currentStage = STAGE_BUILD_REQUIRED_BUILDINGS;
        } else {
            currentStage = STAGE_POPULATION_GROWTH;
            targetPopulation = 10;
        }

        if (houseBuilderSN != -1 && dockBuilderSN == -1) {
            dockBuilderSN = houseBuilderSN;
            dockBuilderReserved = true;
            if (ordinaryVillagers.count(dockBuilderSN)) {
                ordinaryVillagers.erase(dockBuilderSN);
            }
        }
        return;
    }

    if (houseCount + housesUnderConstruction < TARGET_HOUSES) {
        int buildX, buildY;
        if (this->findNearbyPosition(buildX, buildY, info, 2, 2, BUILDING_HOME)) {
            if (info.Wood >= BUILD_HOUSE_WOOD) {
                tagFarmer* builder = nullptr;

                for (const auto& farmer : info.farmers) {
                    if (farmer.SN == houseBuilderSN && farmer.FarmerSort == 0 && farmer.NowState == HUMAN_STATE_IDLE) {
                        builder = const_cast<tagFarmer*>(&farmer);
                        break;
                    }
                }

                if (builder == nullptr && houseBuilderSN == -1) {
                    for (const auto& farmer : info.farmers) {
                        if (farmer.FarmerSort == 0 && farmer.NowState == HUMAN_STATE_IDLE) {
                            builder = const_cast<tagFarmer*>(&farmer);
                            houseBuilderSN = farmer.SN;
                            break;
                        }
                    }
                }

                if (builder != nullptr) {
                    int ret = HumanBuild(builder->SN, BUILDING_HOME, buildX, buildY);
                    if (ret > 0) {
                        housesUnderConstruction++;
                        for (int i = 0; i < 2; i++) {
                            for (int j = 0; j < 2; j++) {
                                occupiedPositions.insert({buildX+i, buildY+j});
                            }
                        }
                    }
                }
            } else {
                ;
            }
        }
    }

    this->assignTasksToVillagersWithLimits(info, !dockBuilt);
    this->assignFishingBoatsToFishResources(info);
}

void UsrAI::buildFishingBoatPhase(const tagInfo& info) {
    fishingBoatCount = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 2) {
            fishingBoatCount++;
        }
    }

    if (fishingBoatCount >= TARGET_FISHING_BOATS) {
        fishingBoatBuilt = true;
        currentStage = STAGE_UPGRADE_AGE;
        return;
    }

    bool productionAttemptedThisFrame = false;
    for (const auto& building : info.buildings) {
        if (building.Type == BUILDING_DOCK && building.Percent == 100) {
            int boatsProducedByThisDock = dockFishingBoatCount[building.SN];
            if (boatsProducedByThisDock < TARGET_BOATS_PER_DOCK) {
                if (building.Project == 0 && info.Wood >= BUILDING_DOCK_CREATE_SAILING_WOOD) {
                    int ret = BuildingAction(building.SN, BUILDING_DOCK_CREATE_SAILING);
                    if (ret > 0) {
                        dockFishingBoatCount[building.SN]++;
                        productionAttemptedThisFrame = true;
                        return;
                    }
                }
            }
        }
    }

    if (!productionAttemptedThisFrame && fishingBoatCount < TARGET_FISHING_BOATS) {
        bool allDocksAtCapacity = true;
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_DOCK && building.Percent == 100) {
                if (dockFishingBoatCount[building.SN] < TARGET_BOATS_PER_DOCK) {
                    allDocksAtCapacity = false;
                    break;
                }
            }
        }

        if (allDocksAtCapacity && completedDocksCount < TARGET_DOCKS_NUM) {
            currentStage = STAGE_BUILD_REQUIRED_BUILDINGS;
            return;
        }
    }

    this->assignTasksToVillagersWithLimits(info, false);
    this->assignFishingBoatsToFishResources(info);
}

void UsrAI::assignFishingBoatsToFishResources(const tagInfo& info) {
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 2 && farmer.NowState == HUMAN_STATE_IDLE) {
            int targetFishSN = -1;
            double minDistance = -1;

            for (const auto& resource : info.resources) {
                if (resource.Type == RESOURCE_FISH && resource.Cnt > 0) {
                    double distance = abs(farmer.BlockDR - resource.BlockDR) + abs(farmer.BlockUR - resource.BlockUR);
                    if (targetFishSN == -1 || distance < minDistance) {
                        minDistance = distance;
                        targetFishSN = resource.SN;
                    }
                }
            }

            if (targetFishSN != -1) {
                HumanAction(farmer.SN, targetFishSN);
            } else {
                int exploreX = rand() % 128;
                int exploreY = rand() % 128;
                if (this->isOcean((*info.theMap)[exploreX][exploreY].type)) {
                    HumanMove(farmer.SN, exploreX * BLOCKSIDELENGTH, exploreY * BLOCKSIDELENGTH);
                }
            }
        }
    }
}

bool UsrAI::findCoastalLandingPosition(int& x, int& y, const tagInfo& info) {
    const int searchRadius = 15;
    double minDist = 999999;
    int bestX = -1, bestY = -1;

    for (int r = 1; r <= searchRadius; ++r) {
        for (int i = -r; i <= r; ++i) {
            for (int j = -r; j <= r; ++j) {
                if (abs(i) != r && abs(j) != r) continue;

                int checkX = center_x + i;
                int checkY = center_y + j;

                if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128) continue;

                if (this->isMapCellLand(checkX, checkY, info)) {
                    bool isCoastal = false;
                    const int offsets[8][2] = {
                        {-1, 0}, {1, 0}, {0, -1}, {0, 1},
                        {-1, -1}, {-1, 1}, {1, -1}, {1, 1}
                    };

                    for(const auto& offset : offsets) {
                        int adjX = checkX + offset[0];
                        int adjY = checkY + offset[1];
                        if (adjX >= 0 && adjX < 128 && adjY >= 0 && adjY < 128) {
                            if(this->isOcean((*info.theMap)[adjX][adjY].type)) {
                                isCoastal = true;
                                break;
                            }
                        }
                    }

                    if (isCoastal) {
                        int landCount = 0;
                        for (int dx = -2; dx <= 2; dx++) {
                            for (int dy = -2; dy <= 2; dy++) {
                                int nearX = checkX + dx;
                                int nearY = checkY + dy;
                                if (nearX >= 0 && nearX < 128 && nearY >= 0 && nearY < 128) {
                                    if (this->isMapCellLand(nearX, nearY, info)) {
                                        landCount++;
                                    }
                                }
                            }
                        }

                        if (landCount >= 8) {
                            double dist = sqrt(pow(checkX - center_x, 2) + pow(checkY - center_y, 2));
                            if (dist < minDist) {
                                minDist = dist;
                                bestX = checkX;
                                bestY = checkY;
                            }
                        }
                    }
                }
            }
        }
    }

    if (bestX != -1 && bestY != -1) {
        x = bestX;
        y = bestY;
        return true;
    }

    return false;
}

void UsrAI::assignTransportShipsToShore(const tagInfo& info) {
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 1 && farmer.NowState == HUMAN_STATE_IDLE) {
            int landX, landY;
            if (findCoastalLandingPosition(landX, landY, info)) {
                HumanMove(farmer.SN, landX * BLOCKSIDELENGTH, landY * BLOCKSIDELENGTH);
            }
        }
    }
}

void UsrAI::buildWarshipsPhase(const tagInfo& info) {
    warshipCount = 0;
    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) {
            warshipCount++;
        }
    }

    if (warshipCount >= TARGET_WARSHIPS) {
        fleetsFormed = false;
        currentStage = STAGE_EXPLORE;
        return;
    }

    for (const auto& building : info.buildings) {
        if (building.Type == BUILDING_DOCK && building.Percent == 100 && building.Project == 0) {
            int warshipsProducedByThisDock = dockWarshipCount[building.SN];
            if (warshipsProducedByThisDock < TARGET_WARSHIPS_PER_DOCK) {
                if (info.Wood >= BUILDING_DOCK_CREATE_SHIP_WOOD) {
                    int ret = BuildingAction(building.SN, BUILDING_DOCK_CREATE_SHIP);
                    if (ret > 0) {
                        dockWarshipCount[building.SN]++;
                        return;
                    }
                }
            }
        }
    }

    this->assignTasksToVillagersWithLimits(info, false);
    this->assignFishingBoatsToFishResources(info);
}

void UsrAI::formWarshipFleets(const tagInfo& info) {
    warshipFleets.clear();
    assignedWarships.clear();
    fleetExplorationTargets.clear();
    fleetAttackTargetsSN.clear();

    std::vector<int> availableWarships;
    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) {
            availableWarships.push_back(army.SN);
        }
    }

    std::sort(availableWarships.begin(), availableWarships.end());

    const int MIN_SHIPS_PER_FLEET = 2;
    const int MAX_SHIPS_PER_FLEET = 3;

    int fleetIndex = 0;
    while (availableWarships.size() >= MIN_SHIPS_PER_FLEET) {
        std::vector<int> newFleet;
        int shipsToAssign = std::min(MAX_SHIPS_PER_FLEET, (int)availableWarships.size());

        for (int i = 0; i < shipsToAssign; ++i) {
            newFleet.push_back(availableWarships.back());
            assignedWarships.insert(availableWarships.back());
            availableWarships.pop_back();
        }

        warshipFleets.push_back(newFleet);
        fleetIndex++;
    }
}

void UsrAI::explorePhase(const tagInfo& info) {
    std::vector<int> allWarships;
    double fleetCenterX = 0, fleetCenterY = 0;
    int idleCount = 0;

    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) {
            allWarships.push_back(army.SN);
            fleetCenterX += army.BlockDR;
            fleetCenterY += army.BlockUR;

            if (army.NowState == HUMAN_STATE_IDLE) {
                idleCount++;
            }
        }
    }

    if (allWarships.empty()) {
        return;
    }

    fleetCenterX /= allWarships.size();
    fleetCenterY /= allWarships.size();

    static int currentEnemyTargetSN = -1;
    static int combatCooldown = 0;

    if (currentEnemyTargetSN != -1) {
        bool targetExists = false;
        for (const auto& enemy : info.enemy_armies) {
            if (enemy.SN == currentEnemyTargetSN) {
                targetExists = true;
                break;
            }
        }

        if (!targetExists) {
            currentEnemyTargetSN = -1;
            combatCooldown = 5;
        }
    }

    if (combatCooldown > 0) {
        combatCooldown--;
    }

    if (currentEnemyTargetSN != -1 && combatCooldown == 0) {
        for (int shipSN : allWarships) {
            for (const auto& army : info.armies) {
                if (army.SN == shipSN && army.NowState == HUMAN_STATE_IDLE) {
                    HumanAction(shipSN, currentEnemyTargetSN);
                    break;
                }
            }
        }
        return;
    }

    // 扩展攻击目标，包括所有敌方单位
    if (currentEnemyTargetSN == -1 && combatCooldown == 0) {
        // 先尝试攻击敌方战船
        for (const auto& enemy : info.enemy_armies) {
            if (enemy.Sort == AT_SHIP) {
                double dist = sqrt(pow(fleetCenterX - enemy.BlockDR, 2) +
                                 pow(fleetCenterY - enemy.BlockUR, 2));
                if (dist <= 40) {
                    currentEnemyTargetSN = enemy.SN;
                    for (int shipSN : allWarships) {
                        for (const auto& army : info.armies) {
                            if (army.SN == shipSN && army.NowState == HUMAN_STATE_IDLE) {
                                HumanAction(shipSN, currentEnemyTargetSN);
                                break;
                            }
                        }
                    }
                    return;
                }
            }
        }

        // 如果没有敌方战船，攻击其他敌方单位
        for (const auto& enemy : info.enemy_armies) {
            if (enemy.Sort != AT_SHIP) {  // 陆地单位
                double dist = sqrt(pow(fleetCenterX - enemy.BlockDR, 2) +
                                 pow(fleetCenterY - enemy.BlockUR, 2));
                if (dist <= 40) {
                    currentEnemyTargetSN = enemy.SN;
                    for (int shipSN : allWarships) {
                        for (const auto& army : info.armies) {
                            if (army.SN == shipSN && army.NowState == HUMAN_STATE_IDLE) {
                                HumanAction(shipSN, currentEnemyTargetSN);
                                break;
                            }
                        }
                    }
                    return;
                }
            }
        }
    }

    this->scanForEnemyContinent(info);

    static int targetX = -1;
    static int targetY = -1;
    static int stuckCounter = 0;
    static int lastIdleCount = 0;
    static std::pair<int, int> lastFleetCenter = {-1, -1};
    static int samePositionCounter = 0;

    bool fleetStuck = false;

    if (abs(fleetCenterX - lastFleetCenter.first) < 3 &&
        abs(fleetCenterY - lastFleetCenter.second) < 3) {
        samePositionCounter++;
        if (samePositionCounter > 20) {
            fleetStuck = true;
        }
    } else {
        samePositionCounter = 0;
    }

    lastFleetCenter = {(int)fleetCenterX, (int)fleetCenterY};

    if (idleCount > allWarships.size() * 0.6) {
        stuckCounter++;
        if (stuckCounter > 10) {
            fleetStuck = true;
        }
    } else {
        stuckCounter = 0;
    }

    bool needNewTarget = false;

    if (targetX == -1 || targetY == -1) {
        needNewTarget = true;
    } else if (fleetStuck) {
        needNewTarget = true;
    } else {
        double distToTarget = sqrt(pow(fleetCenterX - targetX, 2) +
                                  pow(fleetCenterY - targetY, 2));
        if (distToTarget < 8) {
            needNewTarget = true;
        }
    }

    if (needNewTarget) {
        stuckCounter = 0;
        samePositionCounter = 0;

        int bestX = -1, bestY = -1;
        double bestScore = -1;

        for (int x = 10; x < 118; x += 8) {
            for (int y = 10; y < 118; y += 8) {
                double distFromHome = sqrt(pow(x - center_x, 2) + pow(y - center_y, 2));

                if (distFromHome < 45) continue;

                int unknownCount = 0;
                for (int dx = -15; dx <= 15; dx += 3) {
                    for (int dy = -15; dy <= 15; dy += 3) {
                        int checkX = x + dx;
                        int checkY = y + dy;
                        if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                            if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_UNKNOWN) {
                                unknownCount++;
                            }
                        }
                    }
                }
                if (unknownCount == 0) continue;

                bool hasOceanNearby = false;
                for (int dx = -5; dx <= 5; dx++) {
                    for (int dy = -5; dy <= 5; dy++) {
                        int checkX = x + dx;
                        int checkY = y + dy;
                        if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                            if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                                hasOceanNearby = true;
                                break;
                            }
                        }
                    }
                    if (hasOceanNearby) break;
                }

                if (!hasOceanNearby) continue;
                double distanceScore = distFromHome * 3.0;
                double unknownScore = unknownCount * 2.0;
                double distFromFleet = sqrt(pow(x - fleetCenterX, 2) + pow(y - fleetCenterY, 2));
                double fleetDistScore = 0;
                if (distFromFleet < 30) {
                    fleetDistScore = 30;
                } else if (distFromFleet < 50) {
                    fleetDistScore = 20;
                } else {
                    fleetDistScore = 10 - (distFromFleet - 50) * 0.2;
                }
                double edgeBonus = 0;
                if (x < 20 || x > 108 || y < 20 || y > 108) {
                    edgeBonus = 50;
                }

                double totalScore = distanceScore + unknownScore + fleetDistScore + edgeBonus;

                if (totalScore > bestScore) {
                    bestScore = totalScore;
                    bestX = x;
                    bestY = y;
                }
            }
        }

        if (bestX != -1 && bestY != -1) {
            targetX = bestX;
            targetY = bestY;
            double distFromHome = sqrt(pow(targetX - center_x, 2) + pow(targetY - center_y, 2));
        } else {
            static int preferredAngle = -1;
            static int spiralRadius = 50;
            if (preferredAngle == -1) {
                if (center_x < 64 && center_y < 64) {
                    preferredAngle = 45;
                } else if (center_x >= 64 && center_y < 64) {
                    preferredAngle = 135;
                } else if (center_x < 64 && center_y >= 64) {
                    preferredAngle = 315;
                } else {
                    preferredAngle = 225;
                }
            }

            static int angleOffset = 0;
            angleOffset += 30;
            if (angleOffset > 90) {
                angleOffset = -90;
                spiralRadius += 10;
                if (spiralRadius > 90) {
                    spiralRadius = 50;
                }
            }

            int currentAngle = preferredAngle + angleOffset;
            double radians = currentAngle * 3.14159 / 180.0;
            targetX = center_x + (int)(spiralRadius * cos(radians));
            targetY = center_y + (int)(spiralRadius * sin(radians));

            targetX = std::max(10, std::min(118, targetX));
            targetY = std::max(10, std::min(118, targetY));
        }
    }

    int movedCount = 0;
    for (size_t i = 0; i < allWarships.size(); ++i) {
        int shipSN = allWarships[i];

        const tagArmy* ship = nullptr;
        for (const auto& army : info.armies) {
            if (army.SN == shipSN) {
                ship = &army;
                break;
            }
        }

        if (!ship) continue;

        if (ship->NowState == HUMAN_STATE_IDLE ||
            (ship->NowState == HUMAN_STATE_WALKING && fleetStuck)) {

            int formation = i % 9;
            int row = formation / 3;
            int col = formation % 3;
            int shipTargetX = targetX + (col - 1) * 2;
            int shipTargetY = targetY + (row - 1) * 2;

            shipTargetX = std::max(5, std::min(123, shipTargetX));
            shipTargetY = std::max(5, std::min(123, shipTargetY));

            int ret = HumanMove(shipSN, shipTargetX * BLOCKSIDELENGTH, shipTargetY * BLOCKSIDELENGTH);

            if (ret > 0) {
                movedCount++;
            }
        }
    }

    int unknownCount = 0;
    int totalCells = 0;
    for (int x = 0; x < 128; x += 4) {
        for (int y = 0; y < 128; y += 4) {
            totalCells++;
            if ((*info.theMap)[x][y].type == MAPPATTERN_UNKNOWN) {
                unknownCount++;
            }
        }
    }

    int exploredPercent = 100 - (unknownCount * 100 / totalCells);

    if (enemyContinentFound && exploredPercent > 70) {
        currentStage = STAGE_BUILD_ARMY;
        return;
    }

    this->assignTasksToVillagersWithLimits(info, false);
    this->assignFishingBoatsToFishResources(info);

    if (transportShipCount < 1) {
        this->manageTransportShipProduction(info);
    }
}

std::pair<int, int> UsrAI::getUnifiedFleetExplorationTarget(const tagInfo& info) {
    double fleetX = 0, fleetY = 0;
    int shipCount = 0;

    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) {
            fleetX += army.BlockDR;
            fleetY += army.BlockUR;
            shipCount++;
        }
    }

    if (shipCount == 0) {
        return {64, 64};
    }

    fleetX /= shipCount;
    fleetY /= shipCount;

    std::pair<int, int> bestTarget = {-1, -1};
    double maxScore = -1;

    for (int angle = 0; angle < 360; angle += 15) {
        double radians = angle * 3.14159 / 180.0;

        for (int radius = 30; radius <= 80; radius += 10) {
            int targetX = center_x + (int)(radius * cos(radians));
            int targetY = center_y + (int)(radius * sin(radians));

            targetX = std::max(8, std::min(120, targetX));
            targetY = std::max(8, std::min(120, targetY));

            if (!isValidOceanPosition(targetX, targetY, info)) {
                continue;
            }
            double score = 0;

            double distFromHome = sqrt(pow(targetX - center_x, 2) + pow(targetY - center_y, 2));
            score += distFromHome * 2;

            int unknownCount = 0;
            for (int dx = -10; dx <= 10; dx += 5) {
                for (int dy = -10; dy <= 10; dy += 5) {
                    int checkX = targetX + dx;
                    int checkY = targetY + dy;
                    if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                        if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_UNKNOWN) {
                            unknownCount++;
                        }
                    }
                }
            }
            score += unknownCount * 10;

            bool nearPossibleLand = false;
            for (int dx = -15; dx <= 15; dx += 5) {
                for (int dy = -15; dy <= 15; dy += 5) {
                    int checkX = targetX + dx;
                    int checkY = targetY + dy;
                    if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                        if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_GRASS) {
                            double landDist = sqrt(pow(checkX - center_x, 2) + pow(checkY - center_y, 2));
                            if (landDist > 35) {
                                nearPossibleLand = true;
                                score += 50;
                                break;
                            }
                        }
                    }
                }
                if (nearPossibleLand) break;
            }

            double distFromFleet = sqrt(pow(targetX - fleetX, 2) + pow(targetY - fleetY, 2));
            if (distFromFleet > 50) {
                score -= (distFromFleet - 50);
            }

            bool alreadyExplored = false;
            for (const auto& sector : exploredSectors) {
                if (abs(sector.first - targetX) < 10 && abs(sector.second - targetY) < 10) {
                    alreadyExplored = true;
                    break;
                }
            }
            if (alreadyExplored) {
                score *= 0.3;
            }

            if (score > maxScore) {
                maxScore = score;
                bestTarget = {targetX, targetY};
            }
        }
    }

    if (bestTarget.first != -1) {
        double distToTarget = sqrt(pow(fleetX - bestTarget.first, 2) +
                                  pow(fleetY - bestTarget.second, 2));
        if (distToTarget < 8) {
            exploredSectors.push_back(bestTarget);
        }

        return bestTarget;
    }

    fleetExplorationRadius += 5;
    if (fleetExplorationRadius > 70) {
        fleetExplorationRadius = 20;
    }

    double angle = (info.GameFrame % 360) * 3.14159 / 180.0;
    int spiralX = center_x + (int)(fleetExplorationRadius * cos(angle));
    int spiralY = center_y + (int)(fleetExplorationRadius * sin(angle));

    spiralX = std::max(8, std::min(120, spiralX));
    spiralY = std::max(8, std::min(120, spiralY));

    return {spiralX, spiralY};
}

void UsrAI::initializeExplorationZones(const tagInfo& info) {
    explorationZones.clear();

    const int ZONE_SIZE = 60;
    const int MIN_DISTANCE_BETWEEN_ZONES = 8;

    std::vector<std::pair<int, int>> quadrantCenters = {
        {32, 32},
        {96, 32},
        {32, 96},
        {96, 96}
    };

    for (const auto& center : quadrantCenters) {
        for (int dx = -24; dx <= 24; dx += ZONE_SIZE) {
            for (int dy = -24; dy <= 24; dy += ZONE_SIZE) {
                int x = center.first + dx;
                int y = center.second + dy;

                if (x >= 8 && x < 120 && y >= 8 && y < 120) {
                    bool tooClose = false;
                    for (const auto& existing : explorationZones) {
                        int dist = abs(x - existing.first) + abs(y - existing.second);
                        if (dist < MIN_DISTANCE_BETWEEN_ZONES) {
                            tooClose = true;
                            break;
                        }
                    }

                    if (!tooClose && isValidOceanPosition(x, y, info)) {
                        explorationZones.push_back({x, y});
                    }
                }
            }
        }
    }

    for (int i = 16; i < 112; i += 16) {
        if (isValidOceanPosition(i, 16, info)) explorationZones.push_back({i, 16});
        if (isValidOceanPosition(i, 112, info)) explorationZones.push_back({i, 112});
        if (isValidOceanPosition(16, i, info)) explorationZones.push_back({16, i});
        if (isValidOceanPosition(112, i, info)) explorationZones.push_back({112, i});
    }

    explorationZonesInitialized = true;
}

bool UsrAI::findValidExplorationTarget(int fleetIndex, int& targetX, int& targetY, const tagInfo& info) {
    const tagArmy* fleetLeader = nullptr;
    if (!warshipFleets[fleetIndex].empty()) {
        int leaderSN = warshipFleets[fleetIndex][0];
        for (const auto& army : info.armies) {
            if (army.SN == leaderSN) {
                fleetLeader = &army;
                break;
            }
        }
    }

    if (!fleetLeader) return false;
    int quadrant = fleetIndex % 4;

    std::vector<std::vector<int>> quadrantBounds = {
        {8, 64, 8, 64},
        {64, 120, 8, 64},
        {8, 64, 64, 120},
        {64, 120, 64, 120}
    };

    auto bounds = quadrantBounds[quadrant];
    int minX = bounds[0], maxX = bounds[1];
    int minY = bounds[2], maxY = bounds[3];

    double minDist = 1e9;
    bool foundTarget = false;

    for (int x = minX; x < maxX; x += 4) {
        for (int y = minY; y < maxY; y += 4) {
            if ((*info.theMap)[x][y].type == MAPPATTERN_UNKNOWN) {
                bool tooClose = false;
                for (const auto& otherTarget : fleetExplorationTargets) {
                    if (otherTarget.first != fleetIndex) {
                        double dist = sqrt(pow(x - otherTarget.second.first, 2) +
                                         pow(y - otherTarget.second.second, 2));
                        if (dist < 15) {
                            tooClose = true;
                            break;
                        }
                    }
                }

                if (!tooClose) {
                    double dist = sqrt(pow(x - fleetLeader->BlockDR, 2) +
                                     pow(y - fleetLeader->BlockUR, 2));
                    if (dist < minDist) {
                        minDist = dist;
                        targetX = x;
                        targetY = y;
                        foundTarget = true;
                    }
                }
            }
        }
    }

    if (!foundTarget) {
        for (int x = 8; x < 120; x += 6) {
            for (int y = 8; y < 120; y += 6) {
                if ((*info.theMap)[x][y].type == MAPPATTERN_UNKNOWN) {
                    bool tooClose = false;
                    for (const auto& otherTarget : fleetExplorationTargets) {
                        if (otherTarget.first != fleetIndex) {
                            double dist = sqrt(pow(x - otherTarget.second.first, 2) +
                                             pow(y - otherTarget.second.second, 2));
                            if (dist < 12) {
                                tooClose = true;
                                break;
                            }
                        }
                    }

                    if (!tooClose) {
                        double dist = sqrt(pow(x - fleetLeader->BlockDR, 2) +
                                         pow(y - fleetLeader->BlockUR, 2));
                        if (dist < minDist) {
                            minDist = dist;
                            targetX = x;
                            targetY = y;
                            foundTarget = true;
                        }
                    }
                }
            }
        }
    }

    if (!foundTarget) {
        for (int x = 16; x < 112; x += 8) {
            for (int y = 16; y < 112; y += 8) {
                if ((*info.theMap)[x][y].type == MAPPATTERN_OCEAN) {
                    bool nearUnknown = false;
                    for (int dx = -8; dx <= 8; dx += 4) {
                        for (int dy = -8; dy <= 8; dy += 4) {
                            int checkX = x + dx;
                            int checkY = y + dy;
                            if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                                if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_UNKNOWN) {
                                    nearUnknown = true;
                                    break;
                                }
                            }
                        }
                        if (nearUnknown) break;
                    }

                    if (nearUnknown) {
                        bool tooClose = false;
                        for (const auto& otherTarget : fleetExplorationTargets) {
                            if (otherTarget.first != fleetIndex) {
                                double dist = sqrt(pow(x - otherTarget.second.first, 2) +
                                                 pow(y - otherTarget.second.second, 2));
                                if (dist < 10) {
                                    tooClose = true;
                                    break;
                                }
                            }
                        }

                        if (!tooClose) {
                            double dist = sqrt(pow(x - fleetLeader->BlockDR, 2) +
                                             pow(y - fleetLeader->BlockUR, 2));
                            if (dist < minDist) {
                                minDist = dist;
                                targetX = x;
                                targetY = y;
                                foundTarget = true;
                            }
                        }
                    }
                }
            }
        }
    }
    return foundTarget;
}

std::pair<int, int> UsrAI::getPatrolTarget(int fleetIndex, const tagInfo& info) {
    bool needNewTarget = true;

    if (fleetPatrolTargets.count(fleetIndex)) {
        auto currentTarget = fleetPatrolTargets[fleetIndex];

        if (!warshipFleets[fleetIndex].empty()) {
            int leaderSN = warshipFleets[fleetIndex][0];
            for (const auto& army : info.armies) {
                if (army.SN == leaderSN) {
                    double dist = sqrt(pow(army.BlockDR - currentTarget.first, 2) +
                                     pow(army.BlockUR - currentTarget.second, 2));
                    if (dist > 5) {
                        needNewTarget = false;
                    }
                    break;
                }
            }
        }
    }

    if (!needNewTarget) {
        return fleetPatrolTargets[fleetIndex];
    }

    int patrolPattern = fleetIndex % 4;
    int timeOffset = (info.GameFrame / 200 + fleetIndex * 3) % 16;

    std::pair<int, int> newTarget;

    switch (patrolPattern) {
        case 0:
            {
                std::vector<std::pair<int, int>> horizontalPath = {
                    {20 + fleetIndex * 5, 25 + fleetIndex * 8},
                    {40 + fleetIndex * 5, 25 + fleetIndex * 8},
                    {60 + fleetIndex * 5, 25 + fleetIndex * 8},
                    {80 + fleetIndex * 5, 25 + fleetIndex * 8},
                    {100 - fleetIndex * 5, 25 + fleetIndex * 8},
                    {100 - fleetIndex * 5, 45 + fleetIndex * 8},
                    {80 + fleetIndex * 5, 45 + fleetIndex * 8},
                    {60 + fleetIndex * 5, 45 + fleetIndex * 8},
                    {40 + fleetIndex * 5, 45 + fleetIndex * 8},
                    {20 + fleetIndex * 5, 45 + fleetIndex * 8},
                    {20 + fleetIndex * 5, 65 + fleetIndex * 8},
                    {40 + fleetIndex * 5, 65 + fleetIndex * 8},
                    {60 + fleetIndex * 5, 65 + fleetIndex * 8},
                    {80 + fleetIndex * 5, 65 + fleetIndex * 8},
                    {100 - fleetIndex * 5, 65 + fleetIndex * 8},
                    {100 - fleetIndex * 5, 85 + fleetIndex * 8}
                };
                newTarget = horizontalPath[timeOffset % horizontalPath.size()];
            }
            break;

        case 1:
            {
                std::vector<std::pair<int, int>> verticalPath = {
                    {25 + fleetIndex * 12, 20},
                    {25 + fleetIndex * 12, 35},
                    {25 + fleetIndex * 12, 50},
                    {25 + fleetIndex * 12, 65},
                    {25 + fleetIndex * 12, 80},
                    {25 + fleetIndex * 12, 95},
                    {45 + fleetIndex * 12, 95},
                    {45 + fleetIndex * 12, 80},
                    {45 + fleetIndex * 12, 65},
                    {45 + fleetIndex * 12, 50},
                    {45 + fleetIndex * 12, 35},
                    {45 + fleetIndex * 12, 20},
                    {65 + fleetIndex * 12, 20},
                    {65 + fleetIndex * 12, 35},
                    {65 + fleetIndex * 12, 50},
                    {65 + fleetIndex * 12, 65}
                };
                newTarget = verticalPath[timeOffset % verticalPath.size()];
            }
            break;

        case 2:
            {
                if ((timeOffset % 8) < 4) {
                    int step = timeOffset % 4;
                    newTarget = {25 + step * 20 + fleetIndex * 4, 25 + step * 20 + fleetIndex * 4};
                } else {
                    int step = (timeOffset % 4);
                    newTarget = {105 - step * 20 - fleetIndex * 4, 25 + step * 20 + fleetIndex * 4};
                }
            }
            break;

        case 3:
            {
                double angle = (timeOffset * 22.5 + fleetIndex * 30.0) * 3.14159 / 180.0;
                int radius = 20 + fleetIndex * 6;
                int centerX = 64 + (fleetIndex % 2 == 0 ? -15 : 15);
                int centerY = 64 + (fleetIndex < 2 ? -15 : 15);
                newTarget = {
                    centerX + (int)(radius * cos(angle)),
                    centerY + (int)(radius * sin(angle))
                };
            }
            break;
    }

    newTarget.first = std::max(16, std::min(112, newTarget.first));
    newTarget.second = std::max(16, std::min(112, newTarget.second));

    int retryCount = 0;
    while (!isValidOceanPosition(newTarget.first, newTarget.second, info) && retryCount < 5) {
        newTarget.first += (rand() % 11 - 5);
        newTarget.second += (rand() % 11 - 5);
        newTarget.first = std::max(16, std::min(112, newTarget.first));
        newTarget.second = std::max(16, std::min(112, newTarget.second));
        retryCount++;
    }

    if (!isValidOceanPosition(newTarget.first, newTarget.second, info)) {
        newTarget = {32 + fleetIndex * 16, 32 + fleetIndex * 16};
    }

    fleetPatrolTargets[fleetIndex] = newTarget;
    return newTarget;
}

bool UsrAI::isValidOceanPosition(int x, int y, const tagInfo& info) {
    if (x < 0 || y < 0 || x >= 128 || y >= 128) {
        return false;
    }
    return (*info.theMap)[x][y].type == MAPPATTERN_OCEAN;
}

bool UsrAI::isPositionNearMapEdge(int x, int y) {
    const int EDGE_THRESHOLD = 5;
    return (x < EDGE_THRESHOLD || y < EDGE_THRESHOLD ||
            x >= (128 - EDGE_THRESHOLD) || y >= (128 - EDGE_THRESHOLD));
}

void UsrAI::loadVillagersOntoTransports(const tagInfo& info) {
    // 计算敌方大陆上的村民数量
    villagersTransported = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 0) {  // 确保是陆地村民
            int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
            if (dist > 20) {
                villagersTransported++;
            }
        }
    }

    // 修改限制为TARGET_GOLD_MINERS
    if (villagersTransported >= TARGET_GOLD_MINERS) {
        DebugText("已有足够村民在敌方大陆: " + std::to_string(villagersTransported) +
                  "/" + std::to_string(TARGET_GOLD_MINERS));
        return;
    }

    if (!enemyContinentFound) {
        DebugText("敌方大陆未发现，运输船不出发");
        return;
    }

    // 获取所有运输船
    std::vector<tagFarmer*> transports;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 1) {  // 1表示运输船
            transports.push_back(const_cast<tagFarmer*>(&farmer));
        }
    }

    if (transports.empty()) {
        DebugText("没有找到运输船（FarmerSort==1）");
        return;
    }

    DebugText("发现 " + std::to_string(transports.size()) + " 艘运输船");

    // 为每艘运输船维护独立的状态
    static std::map<int, int> transportLoadingStartFrame;
    static std::map<int, bool> transportDeparted;
    static std::map<int, int> lastTransportResource;
    static std::map<int, int> lastMovementFrame;
    static std::map<int, std::pair<int, int>> lastTransportPosition;
    static std::map<int, int> moveFailureCount;

    // 获取战船舰队位置
    std::pair<int, int> fleetCenter = getWarshipFleetCenter(info);

    // 处理每艘运输船
    for (auto* transport : transports) {
        int transportSN = transport->SN;
        int distFromCenter = abs(transport->BlockDR - center_x) + abs(transport->BlockUR - center_y);

        // 检查运输船当前位置的地形
        int currentTerrainType = (*info.theMap)[transport->BlockDR][transport->BlockUR].type;
        std::string terrainStr = "未知";
        if (currentTerrainType == MAPPATTERN_OCEAN) terrainStr = "海洋";
        else if (currentTerrainType == MAPPATTERN_GRASS) terrainStr = "陆地";
        else if (currentTerrainType == MAPPATTERN_UNKNOWN) terrainStr = "未探索";

        DebugText("处理运输船 SN:" + std::to_string(transportSN) +
                  ", 位置:(" + std::to_string(transport->BlockDR) + "," +
                  std::to_string(transport->BlockUR) + "), 地形:" + terrainStr +
                  ", 载员:" + std::to_string(transport->Resource) + "/5, 状态:" +
                  std::to_string(transport->NowState));

        // 如果运输船在陆地上，这是个严重问题
        if (currentTerrainType == MAPPATTERN_GRASS) {
            DebugText("警告：运输船 " + std::to_string(transportSN) + " 在陆地上！需要移到海洋");

            // 寻找最近的海洋格子
            int nearestOceanX = -1, nearestOceanY = -1;
            double minDist = 999999;

            for (int dx = -10; dx <= 10; dx++) {
                for (int dy = -10; dy <= 10; dy++) {
                    int checkX = transport->BlockDR + dx;
                    int checkY = transport->BlockUR + dy;

                    if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                        if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                            double dist = sqrt(dx*dx + dy*dy);
                            if (dist < minDist) {
                                minDist = dist;
                                nearestOceanX = checkX;
                                nearestOceanY = checkY;
                            }
                        }
                    }
                }
            }

            if (nearestOceanX != -1 && nearestOceanY != -1) {
                DebugText("尝试将运输船移到最近的海洋: (" + std::to_string(nearestOceanX) +
                          "," + std::to_string(nearestOceanY) + ")");

                int ret = HumanMove(transportSN,
                                  nearestOceanX * BLOCKSIDELENGTH,
                                  nearestOceanY * BLOCKSIDELENGTH);

                DebugText("移动到海洋命令返回值: " + std::to_string(ret));
                if (ret > 0) {
                    transportDeparted[transportSN] = false;  // 先移到海洋，再出发
                }
            }
            continue;  // 先解决位置问题，下一帧再处理出发
        }

        // 初始化新运输船的状态
        if (transportDeparted.find(transportSN) == transportDeparted.end()) {
            transportDeparted[transportSN] = false;
            lastTransportResource[transportSN] = transport->Resource;
            transportLoadingStartFrame[transportSN] = -1;
            lastMovementFrame[transportSN] = -1;
            lastTransportPosition[transportSN] = {transport->BlockDR, transport->BlockUR};
            moveFailureCount[transportSN] = 0;
            DebugText("初始化新运输船 SN: " + std::to_string(transportSN));
        }

        // 检查运输船是否真的在移动
        if (transportDeparted[transportSN] && transport->NowState == HUMAN_STATE_IDLE) {
            auto lastPos = lastTransportPosition[transportSN];
            if (lastPos.first == transport->BlockDR && lastPos.second == transport->BlockUR) {
                // 位置没变
                moveFailureCount[transportSN]++;
                if (moveFailureCount[transportSN] > 3) {
                    DebugText("运输船 " + std::to_string(transportSN) +
                              " 移动失败超过3次，重置状态");
                    transportDeparted[transportSN] = false;
                    moveFailureCount[transportSN] = 0;
                }
            } else {
                moveFailureCount[transportSN] = 0;  // 移动成功，重置计数
            }
        }
        lastTransportPosition[transportSN] = {transport->BlockDR, transport->BlockUR};

        // 如果运输船资源增加了，说明有村民上船
        if (transport->Resource > lastTransportResource[transportSN]) {
            DebugText("运输船 " + std::to_string(transportSN) +
                      " 村民上船，当前载员: " + std::to_string(transport->Resource) + "/5");
            transportDeparted[transportSN] = false;

            if (lastTransportResource[transportSN] == 0 && transport->Resource > 0) {
                transportLoadingStartFrame[transportSN] = info.GameFrame;
                DebugText("运输船 " + std::to_string(transportSN) +
                          " 开始装载，记录起始帧: " + std::to_string(info.GameFrame));
            }
        }
        lastTransportResource[transportSN] = transport->Resource;

        // 如果运输船正在移动
        if (transport->NowState == HUMAN_STATE_WALKING) {
            int targetX = (int)(transport->DR0 / BLOCKSIDELENGTH);
            int targetY = (int)(transport->UR0 / BLOCKSIDELENGTH);

            DebugText("运输船 " + std::to_string(transportSN) +
                      " 正在移动 - 当前:(" + std::to_string(transport->BlockDR) + "," +
                      std::to_string(transport->BlockUR) + ") 目标:(" +
                      std::to_string(targetX) + "," + std::to_string(targetY) + ")");

            transportDeparted[transportSN] = true;
            moveFailureCount[transportSN] = 0;
            continue;
        }

        // 如果运输船空闲但标记为已出发，说明有问题
        if (transport->NowState == HUMAN_STATE_IDLE && transportDeparted[transportSN] && transport->Resource > 0) {
            DebugText("警告：运输船 " + std::to_string(transportSN) +
                      " 空闲但标记为已出发，重置状态");
            transportDeparted[transportSN] = false;
        }

        // 如果运输船有载员且未出发，检查是否应该出发
        if (transport->Resource > 0 && !transportDeparted[transportSN] && transport->NowState == HUMAN_STATE_IDLE) {
            bool shouldDepart = false;
            std::string departReason = "";

            // 条件1：满5人
            if (transport->Resource >= 5) {
                shouldDepart = true;
                departReason = "满载5人";
            }

            // 条件2：等待超过250帧
            if (!shouldDepart && transportLoadingStartFrame[transportSN] != -1) {
                int waitedFrames = info.GameFrame - transportLoadingStartFrame[transportSN];
                if (waitedFrames >= 250) {
                    shouldDepart = true;
                    departReason = "等待超过250帧 (" + std::to_string(waitedFrames) + "帧)";
                } else {
                    DebugText("运输船 " + std::to_string(transportSN) + " 已等待 " +
                              std::to_string(waitedFrames) + "/250 帧，载员: " +
                              std::to_string(transport->Resource) + "/5");
                }
            }

            if (shouldDepart) {
                DebugText("运输船 " + std::to_string(transportSN) + " 准备出发，原因: " + departReason);

                // 优先前往战船舰队
                if (fleetCenter.first != -1 && fleetCenter.second != -1) {
                    // 查找一条可行的路径
                    int targetX = fleetCenter.first;
                    int targetY = fleetCenter.second;

                    // 检查目标位置地形
                    int targetTerrain = (*info.theMap)[targetX][targetY].type;
                    DebugText("目标位置 (" + std::to_string(targetX) + "," +
                              std::to_string(targetY) + ") 地形类型: " + std::to_string(targetTerrain));

                    // 如果目标不是海洋，寻找附近的海洋或海岸
                    if (targetTerrain != MAPPATTERN_OCEAN) {
                        bool foundValidTarget = false;

                        // 寻找附近的海洋格子
                        for (int radius = 1; radius <= 20 && !foundValidTarget; radius++) {
                            for (int dx = -radius; dx <= radius && !foundValidTarget; dx++) {
                                for (int dy = -radius; dy <= radius && !foundValidTarget; dy++) {
                                    if (abs(dx) != radius && abs(dy) != radius) continue;

                                    int checkX = fleetCenter.first + dx;
                                    int checkY = fleetCenter.second + dy;

                                    if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                                        if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                                            targetX = checkX;
                                            targetY = checkY;
                                            foundValidTarget = true;
                                            DebugText("找到附近海洋目标: (" + std::to_string(targetX) +
                                                      "," + std::to_string(targetY) + ")");
                                        }
                                    }
                                }
                            }
                        }

                        // 如果还是没找到，寻找海岸（运输船可以靠岸卸载）
                        if (!foundValidTarget) {
                            for (int radius = 1; radius <= 20 && !foundValidTarget; radius++) {
                                for (int dx = -radius; dx <= radius && !foundValidTarget; dx++) {
                                    for (int dy = -radius; dy <= radius && !foundValidTarget; dy++) {
                                        if (abs(dx) != radius && abs(dy) != radius) continue;

                                        int checkX = fleetCenter.first + dx;
                                        int checkY = fleetCenter.second + dy;

                                        if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                                            // 检查是否是海岸（陆地但靠近海洋）
                                            if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_GRASS) {
                                                bool nearOcean = false;
                                                for (int ddx = -1; ddx <= 1; ddx++) {
                                                    for (int ddy = -1; ddy <= 1; ddy++) {
                                                        int adjX = checkX + ddx;
                                                        int adjY = checkY + ddy;
                                                        if (adjX >= 0 && adjX < 128 && adjY >= 0 && adjY < 128) {
                                                            if ((*info.theMap)[adjX][adjY].type == MAPPATTERN_OCEAN) {
                                                                nearOcean = true;
                                                                break;
                                                            }
                                                        }
                                                    }
                                                    if (nearOcean) break;
                                                }

                                                if (nearOcean) {
                                                    targetX = checkX;
                                                    targetY = checkY;
                                                    foundValidTarget = true;
                                                    DebugText("找到附近海岸目标: (" + std::to_string(targetX) +
                                                              "," + std::to_string(targetY) + ")");
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // 尝试中间路径点
                    int distToTarget = abs(targetX - transport->BlockDR) + abs(targetY - transport->BlockUR);
                    if (distToTarget > 30) {
                        // 计算中间点
                        int midX = transport->BlockDR + (targetX - transport->BlockDR) / 3;
                        int midY = transport->BlockUR + (targetY - transport->BlockUR) / 3;

                        // 确保中间点是海洋
                        if ((*info.theMap)[midX][midY].type == MAPPATTERN_OCEAN) {
                            targetX = midX;
                            targetY = midY;
                            DebugText("目标太远，先移动到中间点: (" + std::to_string(targetX) +
                                      "," + std::to_string(targetY) + ")");
                        }
                    }

                    DebugText("发送移动命令：运输船 " + std::to_string(transportSN) +
                              " 从 (" + std::to_string(transport->BlockDR) + "," +
                              std::to_string(transport->BlockUR) + ") -> (" +
                              std::to_string(targetX) + "," + std::to_string(targetY) + ")");

                    // 计算实际坐标
                    double targetDR = targetX * BLOCKSIDELENGTH;
                    double targetUR = targetY * BLOCKSIDELENGTH;

                    DebugText("细节坐标: (" + std::to_string(targetDR) + "," +
                              std::to_string(targetUR) + ")");

                    int ret = HumanMove(transportSN, targetDR, targetUR);

                    DebugText("移动命令返回值: " + std::to_string(ret));

                    if (ret > 0) {
                        transportDeparted[transportSN] = true;
                        transportLoadingStartFrame[transportSN] = -1;
                        lastMovementFrame[transportSN] = info.GameFrame;
                        DebugText("运输船 " + std::to_string(transportSN) + " 移动命令成功");
                        moveFailureCount[transportSN] = 0;
                    } else {
                        DebugText("运输船 " + std::to_string(transportSN) +
                                  " 移动命令失败，错误码: " + std::to_string(ret));

                        // 分析错误码
                        switch(ret) {
                            case ACTION_INVALID_SN:
                                DebugText("错误：SN不存在或非法");
                                break;
                            case ACTION_INVALID_LOCATION:
                                DebugText("错误：目标位置超界");
                                break;
                            case ACTION_INVALID_DISTANCE_FAR:
                                DebugText("错误：距离太远");
                                break;
                            default:
                                DebugText("未知错误码: " + std::to_string(ret));
                                break;
                        }

                        moveFailureCount[transportSN]++;
                    }
                } else if (selectedLandingX != -1 && selectedLandingY != -1) {
                    // 使用备用登陆点
                    DebugText("使用备用登陆点: (" + std::to_string(selectedLandingX) +
                              "," + std::to_string(selectedLandingY) + ")");

                    int ret = HumanMove(transportSN,
                                      selectedLandingX * BLOCKSIDELENGTH,
                                      selectedLandingY * BLOCKSIDELENGTH);

                    if (ret > 0) {
                        transportDeparted[transportSN] = true;
                        transportLoadingStartFrame[transportSN] = -1;
                        lastMovementFrame[transportSN] = info.GameFrame;
                        DebugText("运输船前往备用登陆点成功");
                    } else {
                        DebugText("前往登陆点失败，错误码: " + std::to_string(ret));
                    }
                } else {
                    DebugText("错误：没有有效的目标位置");
                }
            }
            continue;
        }

        // 空运输船远离家乡，返回
        if (distFromCenter > 35 && transport->Resource == 0 && transport->NowState == HUMAN_STATE_IDLE) {
            DebugText("运输船 " + std::to_string(transportSN) + " 空船远离家乡，准备返回");

            // 寻找家乡附近的海岸
            int targetX = -1, targetY = -1;
            double minDist = 999999;

            for (int dx = -10; dx <= 10; dx++) {
                for (int dy = -10; dy <= 10; dy++) {
                    int checkX = center_x + dx;
                    int checkY = center_y + dy;

                    if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                        if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                            bool nearLand = false;
                            for (int ddx = -1; ddx <= 1; ddx++) {
                                for (int ddy = -1; ddy <= 1; ddy++) {
                                    int landX = checkX + ddx;
                                    int landY = checkY + ddy;
                                    if (landX >= 0 && landX < 128 && landY >= 0 && landY < 128) {
                                        if ((*info.theMap)[landX][landY].type == MAPPATTERN_GRASS) {
                                            nearLand = true;
                                            break;
                                        }
                                    }
                                }
                                if (nearLand) break;
                            }

                            if (nearLand) {
                                double dist = sqrt(pow(checkX - center_x, 2) + pow(checkY - center_y, 2));
                                if (dist < minDist) {
                                    minDist = dist;
                                    targetX = checkX;
                                    targetY = checkY;
                                }
                            }
                        }
                    }
                }
            }

            if (targetX != -1 && targetY != -1) {
                int ret = HumanMove(transportSN, targetX * BLOCKSIDELENGTH, targetY * BLOCKSIDELENGTH);
                if (ret > 0) {
                    transportDeparted[transportSN] = false;
                    transportLoadingStartFrame[transportSN] = -1;
                    lastMovementFrame[transportSN] = info.GameFrame;
                    DebugText("运输船 " + std::to_string(transportSN) +
                              " 返回家乡: (" + std::to_string(targetX) + "," +
                              std::to_string(targetY) + ")");
                } else {
                    DebugText("运输船 " + std::to_string(transportSN) +
                              " 返回失败，错误码: " + std::to_string(ret));
                }
            }
            continue;
        }

        // 运输船在本土附近，装载村民
        if (distFromCenter <= 35 && transport->Resource < 5 && transport->NowState == HUMAN_STATE_IDLE) {
            DebugText("运输船 " + std::to_string(transportSN) +
                      " 在本土，当前载员: " + std::to_string(transport->Resource) + "/5");

            // 检查运输船是否在合适的位置（靠近陆地的海域）
            bool nearLand = false;
            for (int dx = -2; dx <= 2; dx++) {
                for (int dy = -2; dy <= 2; dy++) {
                    int checkX = transport->BlockDR + dx;
                    int checkY = transport->BlockUR + dy;
                    if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                        if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_GRASS) {
                            nearLand = true;
                            break;
                        }
                    }
                    if (nearLand) break;
                }
            }

            if (!nearLand) {
                DebugText("运输船不靠近陆地，需要移动到海岸");

                int targetX = -1, targetY = -1;
                double minDist = 999999;

                for (int x = center_x - 15; x <= center_x + 15; x++) {
                    for (int y = center_y - 15; y <= center_y + 15; y++) {
                        if (x >= 0 && x < 128 && y >= 0 && y < 128) {
                            if ((*info.theMap)[x][y].type == MAPPATTERN_OCEAN) {
                                bool adjacentToLand = false;
                                for (int dx = -1; dx <= 1; dx++) {
                                    for (int dy = -1; dy <= 1; dy++) {
                                        if (dx == 0 && dy == 0) continue;
                                        int landX = x + dx;
                                        int landY = y + dy;
                                        if (landX >= 0 && landX < 128 && landY >= 0 && landY < 128) {
                                            if ((*info.theMap)[landX][landY].type == MAPPATTERN_GRASS) {
                                                adjacentToLand = true;
                                                break;
                                            }
                                        }
                                    }
                                    if (adjacentToLand) break;
                                }

                                if (adjacentToLand) {
                                    double dist = sqrt(pow(x - transport->BlockDR, 2) +
                                                     pow(y - transport->BlockUR, 2));
                                    if (dist < minDist) {
                                        minDist = dist;
                                        targetX = x;
                                        targetY = y;
                                    }
                                }
                            }
                        }
                    }
                }

                if (targetX != -1 && targetY != -1) {
                    int ret = HumanMove(transportSN, targetX * BLOCKSIDELENGTH, targetY * BLOCKSIDELENGTH);
                    if (ret > 0) {
                        DebugText("运输船 " + std::to_string(transportSN) +
                                  " 移动到海岸: (" + std::to_string(targetX) + "," +
                                  std::to_string(targetY) + ")");
                    } else {
                        DebugText("移动到海岸失败，错误码: " + std::to_string(ret));
                    }
                    continue;
                }
            }

            if (nearLand) {
                int villagersNeeded = 5 - transport->Resource;
                DebugText("运输船 " + std::to_string(transportSN) +
                          " 靠近陆地，需要装载 " + std::to_string(villagersNeeded) + " 个村民");

                std::vector<std::pair<int, double>> availableVillagers;

                for (const auto& villager : info.farmers) {
                    if (villager.FarmerSort == 0) {  // 确保是陆地村民
                        double dist = sqrt(pow(villager.BlockDR - transport->BlockDR, 2) +
                                         pow(villager.BlockUR - transport->BlockUR, 2));

                        if (dist < 25) {
                            if (villager.NowState == HUMAN_STATE_IDLE) {
                                availableVillagers.push_back(std::make_pair(villager.SN, dist));
                            }
                            else if (villager.NowState == HUMAN_STATE_WORKING &&
                                    (int)availableVillagers.size() < villagersNeeded) {
                                bool criticalWork = false;
                                if (info.Wood < 100 || info.Meat < 100) {
                                    criticalWork = true;
                                }

                                if (!criticalWork) {
                                    availableVillagers.push_back(std::make_pair(villager.SN, dist + 100));
                                }
                            }
                        }
                    }
                }

                DebugText("找到 " + std::to_string(availableVillagers.size()) + " 个可用村民");

                std::sort(availableVillagers.begin(), availableVillagers.end(),
                         [](const std::pair<int, double>& a, const std::pair<int, double>& b) {
                             return a.second < b.second;
                         });

                int boardingCommands = 0;
                for (size_t i = 0; i < availableVillagers.size() && boardingCommands < villagersNeeded; i++) {
                    int villagerSN = availableVillagers[i].first;

                    bool villagerExists = false;
                    for (const auto& v : info.farmers) {
                        if (v.SN == villagerSN && v.FarmerSort == 0) {
                            if (v.NowState == HUMAN_STATE_WORKING) {
                                HumanMove(villagerSN, v.DR, v.UR);
                            }
                            villagerExists = true;
                            break;
                        }
                    }

                    if (villagerExists) {
                        int ret = HumanAction(villagerSN, transportSN);
                        if (ret > 0) {
                            boardingCommands++;
                            DebugText("村民 " + std::to_string(villagerSN) + " 上运输船 " +
                                      std::to_string(transportSN) + " 成功");
                        } else {
                            DebugText("村民 " + std::to_string(villagerSN) + " 上船失败，错误码: " +
                                      std::to_string(ret));
                        }
                    }
                }

                if (boardingCommands > 0) {
                    DebugText("本轮命令 " + std::to_string(boardingCommands) + " 个村民上船");
                } else if (availableVillagers.empty()) {
                    DebugText("附近没有可用村民");
                }
            }
            break;  // 只处理一艘需要装载的船，避免同时装载多艘
        }
    }
}

void UsrAI::landInvasionPhase(const tagInfo& info) {
    if (!enemyContinentFound) {
        this->scanForEnemyContinent(info);
        if (!enemyContinentFound) {
            this->explorePhase(info);
            return;
        }
    }

    transportShipCount = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 1) {
            transportShipCount++;
        }
    }

    if (transportShipCount < 1) {
        this->manageTransportShipProduction(info);
        this->assignTasksToVillagersWithLimits(info, false);
        this->assignFishingBoatsToFishResources(info);
        return;
    }

    villagersTransported = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 0) {
            int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
            if (dist > 40) {
                villagersTransported++;
            }
        }
    }

    // 移除原来的运输船控制调用，现在由 manageTransportShips 统一处理
    // this->loadVillagersOntoTransports(info);
    // this->commandInvasionFleet(info);

    this->loadArmyOntoTransports(info);
    this->manageCombat(info);
    this->scanForGold(info);

    bool areaSecured = true;
    int enemiesNearGold = 0;

    if (!goldPositions.empty()) {
        for (const auto& enemy : info.enemy_armies) {
            for (const auto& goldPos : goldPositions) {
                int dist = abs(enemy.BlockDR - goldPos.first) + abs(enemy.BlockUR - goldPos.second);
                if (dist < 15) {
                    areaSecured = false;
                    enemiesNearGold++;
                }
            }
        }

        for (const auto& enemy : info.enemy_buildings) {
            if (enemy.Type == BUILDING_ARROWTOWER) {
                for (const auto& goldPos : goldPositions) {
                    int dist = abs(enemy.BlockDR - goldPos.first) + abs(enemy.BlockUR - goldPos.second);
                    if (dist < 10) {
                        areaSecured = false;
                        enemiesNearGold++;
                    }
                }
            }
        }
    }

    if (enemiesNearGold > 0) {
        // 敌人仍在金矿附近
    }

    if (areaSecured && goldFound && villagersTransported >= 3) {
        currentStage = STAGE_COLLECT_GOLD;
    }

    this->assignTasksToVillagersWithLimits(info, false);
    this->assignFishingBoatsToFishResources(info);

    if (armyCampBuilt) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_ARMYCAMP && building.Percent == 100 && building.Project == 0) {
                if (info.Meat >= BUILDING_ARMYCAMP_CREATE_CLUBMAN_FOOD) {
                    BuildingAction(building.SN, BUILDING_ARMYCAMP_CREATE_CLUBMAN);
                    break;
                }
            }
        }
    }
}

void UsrAI::scanForGold(const tagInfo& info) {
    if (goldFound) return;

    goldPositions.clear();

    for (const auto& res : info.resources) {
        if (res.Type == RESOURCE_GOLD) {
            goldPositions.push_back(std::make_pair(res.BlockDR, res.BlockUR));

            if (!goldFound) {
                goldFound = true;
            }
        }
    }

    if (goldFound) {
        ;
    }
}


void UsrAI::buildArmyPhase(const tagInfo& info) {
    clubmanCount = 0;
    slingerCount = 0;
    bowmanCount = 0;
    scoutCount = 0;
    landArmy.clear();

    for (const auto& army : info.armies) {
        switch(army.Sort) {
            case AT_CLUBMAN:
            case AT_SWORDSMAN:
                clubmanCount++;
                landArmy.push_back(army.SN);
                break;
            case AT_SLINGER:
                slingerCount++;
                landArmy.push_back(army.SN);
                break;
            case AT_BOWMAN:
                bowmanCount++;
                landArmy.push_back(army.SN);
                break;
            case AT_SCOUT:
                scoutCount++;
                landArmy.push_back(army.SN);
                break;
        }
    }

    if (clubmanCount >= TARGET_CLUBMAN &&
        slingerCount >= TARGET_SLINGER &&
        bowmanCount >= TARGET_BOWMAN &&
        scoutCount >= TARGET_SCOUT) {
        currentStage = STAGE_LAND_INVASION;
        return;
    }

    armyCampBuilt = false;
    rangeBuilt = false;
    stableBuilt = false;

    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_ARMYCAMP && b.Percent == 100) armyCampBuilt = true;
        if (b.Type == BUILDING_RANGE && b.Percent == 100) rangeBuilt = true;
        if (b.Type == BUILDING_STABLE && b.Percent == 100) stableBuilt = true;
    }

    bool buildingInProgress = false;
    for (const auto& b : info.buildings) {
        if ((b.Type == BUILDING_ARMYCAMP || b.Type == BUILDING_RANGE || b.Type == BUILDING_STABLE) &&
            b.Percent < 100) {
            buildingInProgress = true;
            break;
        }
    }

    if (!armyCampBuilt && !buildingInProgress) {
        int buildX, buildY;
        if (this->findNearbyPosition(buildX, buildY, info, 3, 3, BUILDING_ARMYCAMP)) {
            if (info.Wood >= BUILD_ARMYCAMP_WOOD) {
                for (const auto& farmer : info.farmers) {
                    if (farmer.NowState == HUMAN_STATE_IDLE && farmer.FarmerSort == 0) {
                        int ret = HumanBuild(farmer.SN, BUILDING_ARMYCAMP, buildX, buildY);
                        if (ret > 0) {
                            for (int i = 0; i < 3; i++) {
                                for (int j = 0; j < 3; j++) {
                                    occupiedPositions.insert({buildX+i, buildY+j});
                                }
                            }
                            buildingInProgress = true;
                        }
                        break;
                    }
                }
            }
        }
    }

    if (!rangeBuilt && !buildingInProgress && armyCampBuilt) {
        int buildX, buildY;
        if (this->findNearbyPosition(buildX, buildY, info, 3, 3, BUILDING_RANGE)) {
            if (info.Wood >= BUILD_RANGE_WOOD) {
                for (const auto& farmer : info.farmers) {
                    if (farmer.NowState == HUMAN_STATE_IDLE && farmer.FarmerSort == 0) {
                        int ret = HumanBuild(farmer.SN, BUILDING_RANGE, buildX, buildY);
                        if (ret > 0) {
                            for (int i = 0; i < 3; i++) {
                                for (int j = 0; j < 3; j++) {
                                    occupiedPositions.insert({buildX+i, buildY+j});
                                }
                            }
                            buildingInProgress = true;
                        }
                        break;
                    }
                }
            }
        }
    }

    if (!stableBuilt && !buildingInProgress && armyCampBuilt) {
        int buildX, buildY;
        if (this->findNearbyPosition(buildX, buildY, info, 3, 3, BUILDING_STABLE)) {
            if (info.Wood >= BUILD_STABLE_WOOD) {
                for (const auto& farmer : info.farmers) {
                    if (farmer.NowState == HUMAN_STATE_IDLE && farmer.FarmerSort == 0) {
                        int ret = HumanBuild(farmer.SN, BUILDING_STABLE, buildX, buildY);
                        if (ret > 0) {
                            for (int i = 0; i < 3; i++) {
                                for (int j = 0; j < 3; j++) {
                                    occupiedPositions.insert({buildX+i, buildY+j});
                                }
                            }
                            buildingInProgress = true;
                        }
                        break;
                    }
                }
            }
        }
    }

    if (!toolUseUpgraded) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_STOCK && building.Percent == 100 && building.Project == 0) {
                if (info.Meat >= BUILDING_STOCK_UPGRADE_USETOOL_FOOD) {
                    int ret = BuildingAction(building.SN, BUILDING_STOCK_UPGRADE_USETOOL);
                    if (ret > 0) {
                        toolUseUpgraded = true;
                    }
                    break;
                }
            }
        }
    }

    this->manageArmyProduction(info);

    this->assignTasksToVillagersWithLimits(info, false);
    this->assignFishingBoatsToFishResources(info);
}

void UsrAI::manageArmyProduction(const tagInfo& info) {
    if (clubmanCount < TARGET_CLUBMAN) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_ARMYCAMP && building.Percent == 100 && building.Project == 0) {
                if (info.Meat >= BUILDING_ARMYCAMP_CREATE_CLUBMAN_FOOD) {
                    int ret = BuildingAction(building.SN, BUILDING_ARMYCAMP_CREATE_CLUBMAN);
                    if (ret > 0) {
                        return;
                    }
                }
            }
        }
    }

    if (slingerCount < TARGET_SLINGER) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_ARMYCAMP && building.Percent == 100 && building.Project == 0) {
                if (info.Meat >= BUILDING_ARMYCAMP_CREATE_SLINGER_FOOD &&
                    info.Stone >= BUILDING_ARMYCAMP_CREATE_SLINGER_STONE) {
                    int ret = BuildingAction(building.SN, BUILDING_ARMYCAMP_CREATE_SLINGER);
                    if (ret > 0) {
                        return;
                    }
                }
            }
        }
    }

    if (bowmanCount < TARGET_BOWMAN) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_RANGE && building.Percent == 100 && building.Project == 0) {
                if (info.Meat >= BUILDING_RANGE_CREATE_BOWMAN_FOOD &&
                    info.Wood >= BUILDING_RANGE_CREATE_BOWMAN_WOOD) {
                    int ret = BuildingAction(building.SN, BUILDING_RANGE_CREATE_BOWMAN);
                    if (ret > 0) {
                        return;
                    }
                }
            }
        }
    }

    if (scoutCount < TARGET_SCOUT) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_STABLE && building.Percent == 100 && building.Project == 0) {
                if (info.Meat >= BUILDING_STABLE_CREATE_SCOUT_FOOD) {
                    int ret = BuildingAction(building.SN, BUILDING_STABLE_CREATE_SCOUT);
                    if (ret > 0) {
                        return;
                    }
                }
            }
        }
    }
}

// 统一运输船管理函数
void UsrAI::manageTransportShips(const tagInfo& info) {
    // 获取所有运输船
    std::vector<const tagFarmer*> transports;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 1) {  // 运输船
            transports.push_back(&farmer);
        }
    }

    if (transports.empty()) {
        return;
    }

    // 清理不存在的运输船状态
    auto it = transportShipStates.begin();
    while (it != transportShipStates.end()) {
        bool found = false;
        for (const auto* transport : transports) {
            if (transport->SN == it->first) {
                found = true;
                break;
            }
        }
        if (!found) {
            transportLastCommandFrame.erase(it->first);
            transportLoadingStartFrame.erase(it->first);
            it = transportShipStates.erase(it);
        } else {
            ++it;
        }
    }

    // 处理每艘运输船
    for (const auto* transport : transports) {
        if (!canControlTransport(transport->SN, info)) {
            continue;
        }

        // 初始化状态
        if (transportShipStates.find(transport->SN) == transportShipStates.end()) {
            transportShipStates[transport->SN] = TRANSPORT_IDLE;
            transportLastCommandFrame[transport->SN] = 0;
        }

        // 检查运输船是否在错误的地形上
        int currentTerrain = (*info.theMap)[transport->BlockDR][transport->BlockUR].type;
        if (currentTerrain == MAPPATTERN_GRASS) {
            DebugText("运输船在陆地上，需要移动到海洋");
            relocateTransportToOcean(transport, info);
            continue;
        }

        // 根据当前状态处理运输船
        int currentState = transportShipStates[transport->SN];
        switch (currentState) {
            case TRANSPORT_IDLE:
                handleTransportIdle(transport, info);
                break;
            case TRANSPORT_LOADING:
                handleTransportLoading(transport, info);
                break;
            case TRANSPORT_DEPARTING:
                handleTransportDeparture(transport, info);
                break;
            case TRANSPORT_RETURNING:
                handleTransportReturn(transport, info);
                break;
            case TRANSPORT_RELOCATING:
                handleTransportRelocating(transport, info);
                break;
        }
    }
}

bool UsrAI::canControlTransport(int transportSN, const tagInfo& info) {
    // 检查冷却时间
    if (transportLastCommandFrame.count(transportSN)) {
        int framesSinceLastCommand = info.GameFrame - transportLastCommandFrame[transportSN];
        if (framesSinceLastCommand < TRANSPORT_COMMAND_COOLDOWN) {
            return false;
        }
    }
    return true;
}

void UsrAI::updateTransportState(int transportSN, TransportState newState, const tagInfo& info) {
    transportShipStates[transportSN] = newState;
    transportLastCommandFrame[transportSN] = info.GameFrame;

    std::string stateStr;
    switch (newState) {
        case TRANSPORT_IDLE: stateStr = "空闲"; break;
        case TRANSPORT_LOADING: stateStr = "装载中"; break;
        case TRANSPORT_DEPARTING: stateStr = "出发中"; break;
        case TRANSPORT_RETURNING: stateStr = "返回中"; break;
        case TRANSPORT_RELOCATING: stateStr = "重新定位"; break;
    }
    DebugText("运输船 " + std::to_string(transportSN) + " 状态变更为: " + stateStr);
}

void UsrAI::handleTransportIdle(const tagFarmer* transport, const tagInfo& info) {
    int distFromHome = abs(transport->BlockDR - center_x) + abs(transport->BlockUR - center_y);

    // 如果运输船在远方且为空船，返回家乡
    if (distFromHome > 35 && transport->Resource == 0) {
        DebugText("运输船 " + std::to_string(transport->SN) +
                  " 空船远离家乡(距离:" + std::to_string(distFromHome) + ")，执行返回");

        // 直接执行返回，而不是只改变状态
        executeTransportReturn(transport, info);
        updateTransportState(transport->SN, TRANSPORT_RETURNING, info);
        return;
    }

    // 如果在家乡附近且有空间，开始装载
    if (distFromHome <= 35 && transport->Resource < 5) {
        DebugText("运输船 " + std::to_string(transport->SN) +
                  " 在家乡附近，开始装载");
        updateTransportState(transport->SN, TRANSPORT_LOADING, info);
        return;
    }

    // 如果有货物，准备出发
    if (transport->Resource > 0) {
        DebugText("运输船 " + std::to_string(transport->SN) +
                  " 有货物(" + std::to_string(transport->Resource) + "/5)，准备出发");
        updateTransportState(transport->SN, TRANSPORT_DEPARTING, info);
        return;
    }
}

void UsrAI::executeTransportReturn(const tagFarmer* transport, const tagInfo& info) {
    // 寻找家乡附近的海岸
    int targetX = -1, targetY = -1;
    double minDist = 999999;

    // 扩大搜索范围，分层搜索
    for (int radius = 10; radius <= 40; radius += 10) {
        bool found = false;

        for (int dx = -radius; dx <= radius; dx++) {
            for (int dy = -radius; dy <= radius; dy++) {
                // 只搜索边缘，不搜索内部（提高效率）
                if (abs(dx) < radius - 5 && abs(dy) < radius - 5) continue;

                int checkX = center_x + dx;
                int checkY = center_y + dy;

                if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                    if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                        bool nearLand = false;

                        // 检查是否靠近陆地
                        for (int ddx = -1; ddx <= 1; ddx++) {
                            for (int ddy = -1; ddy <= 1; ddy++) {
                                int landX = checkX + ddx;
                                int landY = checkY + ddy;
                                if (landX >= 0 && landX < 128 && landY >= 0 && landY < 128) {
                                    if ((*info.theMap)[landX][landY].type == MAPPATTERN_GRASS) {
                                        nearLand = true;
                                        break;
                                    }
                                }
                            }
                            if (nearLand) break;
                        }

                        if (nearLand) {
                            double dist = sqrt(pow(checkX - transport->BlockDR, 2) +
                                             pow(checkY - transport->BlockUR, 2));

                            // 加入距离家的权重，优先选择离家近的位置
                            double homeWeight = sqrt(pow(checkX - center_x, 2) +
                                                    pow(checkY - center_y, 2));
                            double weightedDist = dist + homeWeight * 0.3;

                            if (weightedDist < minDist) {
                                minDist = weightedDist;
                                targetX = checkX;
                                targetY = checkY;
                                found = true;
                            }
                        }
                    }
                }
            }
        }

        // 如果在当前半径找到了，就不继续扩大搜索
        if (found) {
            DebugText("在半径 " + std::to_string(radius) + " 范围内找到返回目标");
            break;
        }
    }

    // 如果还是没找到，尝试寻找任意海洋位置
    if (targetX == -1 && targetY == -1) {
        DebugText("未找到合适海岸，尝试寻找任意海洋位置");

        // 寻找最近的任意海洋位置
        for (int radius = 5; radius <= 60; radius += 5) {
            bool found = false;

            for (int dx = -radius; dx <= radius; dx += 5) {
                for (int dy = -radius; dy <= radius; dy += 5) {
                    int checkX = transport->BlockDR + dx;
                    int checkY = transport->BlockUR + dy;

                    if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                        if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                            // 确保朝向家的方向
                            int distToHome = abs(checkX - center_x) + abs(checkY - center_y);
                            int currentDistToHome = abs(transport->BlockDR - center_x) +
                                                   abs(transport->BlockUR - center_y);

                            if (distToHome < currentDistToHome) {
                                targetX = checkX;
                                targetY = checkY;
                                found = true;
                                DebugText("找到朝向家的海洋位置: (" + std::to_string(targetX) +
                                        "," + std::to_string(targetY) + ")");
                                break;
                            }
                        }
                    }
                }
                if (found) break;
            }
            if (found) break;
        }
    }

    if (targetX != -1 && targetY != -1) {
        // 返回装载时使用0.2偏移
        double targetDR = (targetX + 0.2) * BLOCKSIDELENGTH;
        double targetUR = (targetY + 0.2) * BLOCKSIDELENGTH;

        DebugText("找到返回目标(装载): (" + std::to_string(targetX) + "," +
                  std::to_string(targetY) + "), 距离: " + std::to_string(minDist));

        int ret = HumanMove(transport->SN, targetDR, targetUR);

        if (ret > 0) {
            DebugText("运输船 " + std::to_string(transport->SN) + " 返回命令成功，ID: " +
                      std::to_string(ret));
        } else {
            DebugText("运输船 " + std::to_string(transport->SN) + " 返回命令失败，错误码: " +
                      std::to_string(ret));

            // 分析错误原因
            switch(ret) {
                case ACTION_INVALID_SN:
                    DebugText("错误：SN不存在或非法");
                    break;
                case ACTION_INVALID_LOCATION:
                    DebugText("错误：目标位置超界");
                    break;
                case ACTION_INVALID_DISTANCE_FAR:
                    DebugText("错误：距离太远，尝试分段移动");
                    // 如果距离太远，尝试移动到中间点
                    int midX = transport->BlockDR + (targetX - transport->BlockDR) / 3;
                    int midY = transport->BlockUR + (targetY - transport->BlockUR) / 3;

                    // 确保中间点是海洋
                    if ((*info.theMap)[midX][midY].type == MAPPATTERN_OCEAN) {
                        // 中间点使用0.5偏移（普通移动）
                        double midDR = (midX + 0.5) * BLOCKSIDELENGTH;
                        double midUR = (midY + 0.5) * BLOCKSIDELENGTH;

                        ret = HumanMove(transport->SN, midDR, midUR);
                        if (ret > 0) {
                            DebugText("改为移动到中间点: (" + std::to_string(midX) + "," +
                                      std::to_string(midY) + ")");
                        }
                    }
                    break;
            }
        }
    } else {
        DebugText("错误：未找到合适的返回位置（运输船当前位置: " +
                  std::to_string(transport->BlockDR) + "," +
                  std::to_string(transport->BlockUR) + ")");

        // 最后的尝试：让运输船保持原地
        DebugText("运输船将保持原地等待");
    }
}

void UsrAI::handleTransportLoading(const tagFarmer* transport, const tagInfo& info) {
    // 如果运输船正在移动，先等待它到达目的地
    if (transport->NowState == HUMAN_STATE_WALKING) {
        int targetX = (int)(transport->DR0 / BLOCKSIDELENGTH);
        int targetY = (int)(transport->UR0 / BLOCKSIDELENGTH);

        DebugText("运输船 " + std::to_string(transport->SN) +
                  " 正在移动到 (" + std::to_string(targetX) + "," +
                  std::to_string(targetY) + ")，等待到达");
        return;
    }

    // 检查是否足够靠近陆地（使用更宽松的判定）
    bool nearLand = false;
    int nearLandCount = 0;
    int closestLandDist = 999;

    // 检查稍大范围内的陆地
    for (int dx = -3; dx <= 3; dx++) {
        for (int dy = -3; dy <= 3; dy++) {
            int checkX = transport->BlockDR + dx;
            int checkY = transport->BlockUR + dy;
            if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_GRASS) {
                    int dist = abs(dx) + abs(dy);
                    if (dist <= 2) {  // 距离2格内有陆地就算靠岸
                        nearLand = true;
                        nearLandCount++;
                    }
                    if (dist < closestLandDist) {
                        closestLandDist = dist;
                    }
                }
            }
        }
    }

    // 使用细节坐标进行更精确的判断
    double transportDetailDR = transport->DR;
    double transportDetailUR = transport->UR;

    // 检查细节坐标是否足够靠近陆地边缘
    if (!nearLand && closestLandDist <= 3) {
        // 检查是否在格子边缘附近
        double blockCenterDR = transport->BlockDR * BLOCKSIDELENGTH + BLOCKSIDELENGTH / 2.0;
        double blockCenterUR = transport->BlockUR * BLOCKSIDELENGTH + BLOCKSIDELENGTH / 2.0;

        double distFromCenter = sqrt(pow(transportDetailDR - blockCenterDR, 2) +
                                    pow(transportDetailUR - blockCenterUR, 2));

        // 如果靠近格子边缘（超过格子半径的60%），也算靠岸
        if (distFromCenter > BLOCKSIDELENGTH * 0.3) {
            nearLand = true;
            DebugText("运输船在格子边缘，判定为靠岸");
        }
    }

    DebugText("运输船 " + std::to_string(transport->SN) +
              " 位置:(" + std::to_string(transport->BlockDR) + "," +
              std::to_string(transport->BlockUR) + "), 细节:(" +
              std::to_string(transportDetailDR) + "," +
              std::to_string(transportDetailUR) + "), 附近陆地格子数: " +
              std::to_string(nearLandCount) + ", 最近陆地距离: " +
              std::to_string(closestLandDist));

    if (!nearLand) {
        DebugText("运输船 " + std::to_string(transport->SN) +
                  " 不够靠近陆地，需要移动到海岸");
        moveTransportToCoast(transport, info);
        // 保持LOADING状态，等待到达海岸
        return;
    }

    // 记录装载开始时间
    if (transportLoadingStartFrame.find(transport->SN) == transportLoadingStartFrame.end()) {
        transportLoadingStartFrame[transport->SN] = info.GameFrame;
        DebugText("运输船 " + std::to_string(transport->SN) +
                  " 已靠近陆地，开始装载，当前载员: " +
                  std::to_string(transport->Resource) + "/5");
    }

    // 检查是否满载或超时
    int waitTime = info.GameFrame - transportLoadingStartFrame[transport->SN];

    if (transport->Resource >= 5) {
        DebugText("运输船 " + std::to_string(transport->SN) + " 满载，准备出发");
        transportLoadingStartFrame.erase(transport->SN);
        updateTransportState(transport->SN, TRANSPORT_DEPARTING, info);
        return;
    }

    if (waitTime > TRANSPORT_LOADING_TIMEOUT) {
        DebugText("运输船 " + std::to_string(transport->SN) +
                  " 等待超时(已等待" + std::to_string(waitTime) +
                  "帧)，当前载员: " + std::to_string(transport->Resource) + "/5，准备出发");
        transportLoadingStartFrame.erase(transport->SN);

        // 如果有载员就出发，否则返回空闲状态
        if (transport->Resource > 0) {
            updateTransportState(transport->SN, TRANSPORT_DEPARTING, info);
        } else {
            updateTransportState(transport->SN, TRANSPORT_IDLE, info);
        }
        return;
    }

    DebugText("运输船 " + std::to_string(transport->SN) +
              " 装载中，已载: " + std::to_string(transport->Resource) +
              "/5, 已等待: " + std::to_string(waitTime) + "/" +
              std::to_string(TRANSPORT_LOADING_TIMEOUT) + " 帧");

    // 装载村民
    loadVillagersOntoSingleTransport(transport, info);
}

void UsrAI::handleTransportDeparture(const tagFarmer* transport, const tagInfo& info) {
    // 如果运输船正在移动，等待
    if (transport->NowState == HUMAN_STATE_WALKING) {
        return;
    }

    // 获取战舰舰队中心位置
    std::pair<int, int> fleetCenter = getWarshipFleetCenter(info);

    if (fleetCenter.first != -1 && fleetCenter.second != -1) {
        // 寻找舰队附近最靠近陆地的海洋位置
        int targetX = -1, targetY = -1;
        double minDist = 999999;
        int bestLandDR = -1, bestLandUR = -1;

        // 在舰队附近搜索
        for (int dx = -10; dx <= 10; dx++) {
            for (int dy = -10; dy <= 10; dy++) {
                int checkX = fleetCenter.first + dx;
                int checkY = fleetCenter.second + dy;

                if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                    // 改为寻找陆地格子（而不是海洋格子）
                    if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_GRASS) {
                        // 检查是否靠近海洋（运输船可以到达的陆地）
                        bool nearOcean = false;
                        const int offsets[4][2] = {
                            {-1, 0}, {1, 0}, {0, -1}, {0, 1}
                        };

                        for (const auto& offset : offsets) {
                            int oceanX = checkX + offset[0];
                            int oceanY = checkY + offset[1];

                            if (oceanX >= 0 && oceanX < 128 && oceanY >= 0 && oceanY < 128) {
                                if ((*info.theMap)[oceanX][oceanY].type == MAPPATTERN_OCEAN) {
                                    nearOcean = true;
                                    break;
                                }
                            }
                        }

                        if (nearOcean) {
                            // 计算距离舰队的距离
                            double dist = sqrt(pow(checkX - fleetCenter.first, 2) +
                                             pow(checkY - fleetCenter.second, 2));

                            if (dist < minDist) {
                                minDist = dist;
                                targetX = checkX;
                                targetY = checkY;
                            }
                        }
                    }
                }
            }
        }

        // 如果找到了靠海的陆地位置
        if (targetX != -1 && targetY != -1) {
            // 直接移动到陆地格子的中心
            double targetDR = (targetX + 0.5) * BLOCKSIDELENGTH;
            double targetUR = (targetY + 0.5) * BLOCKSIDELENGTH;

            DebugText("运输船选择陆地卸货位置: (" + std::to_string(targetX) + "," +
                      std::to_string(targetY) + ")");

            int ret = HumanMove(transport->SN, targetDR, targetUR);
            if (ret > 0) {
                updateTransportState(transport->SN, TRANSPORT_IDLE, info);
                DebugText("运输船 " + std::to_string(transport->SN) + " 出发前往陆地卸货点");
            }
        } else {
            // 如果近处没找到合适的陆地，扩大搜索范围
            DebugText("近处未找到靠海陆地，扩大搜索范围");

            for (int radius = 15; radius <= 40; radius += 5) {
                bool found = false;

                for (int dx = -radius; dx <= radius; dx += 5) {
                    for (int dy = -radius; dy <= radius; dy += 5) {
                        int checkX = fleetCenter.first + dx;
                        int checkY = fleetCenter.second + dy;

                        if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                            // 寻找靠海的陆地
                            if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_GRASS) {
                                // 检查是否靠海
                                const int offsets[4][2] = {
                                    {-1, 0}, {1, 0}, {0, -1}, {0, 1}
                                };

                                bool nearOcean = false;
                                for (const auto& offset : offsets) {
                                    int oceanX = checkX + offset[0];
                                    int oceanY = checkY + offset[1];
                                    if (oceanX >= 0 && oceanX < 128 && oceanY >= 0 && oceanY < 128) {
                                        if ((*info.theMap)[oceanX][oceanY].type == MAPPATTERN_OCEAN) {
                                            nearOcean = true;
                                            break;
                                        }
                                    }
                                }

                                if (nearOcean) {
                                    double targetDR = (checkX + 0.5) * BLOCKSIDELENGTH;
                                    double targetUR = (checkY + 0.5) * BLOCKSIDELENGTH;

                                    int ret = HumanMove(transport->SN, targetDR, targetUR);
                                    if (ret > 0) {
                                        updateTransportState(transport->SN, TRANSPORT_IDLE, info);
                                        DebugText("运输船出发前往扩展搜索的陆地卸货点: (" +
                                                  std::to_string(checkX) + "," +
                                                  std::to_string(checkY) + ")");
                                        found = true;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    if (found) break;
                }
                if (found) break;
            }
        }
    } else if (selectedLandingX != -1 && selectedLandingY != -1) {
        // 使用预选的登陆点 - 也要确保是陆地
        if ((*info.theMap)[selectedLandingX][selectedLandingY].type == MAPPATTERN_GRASS) {
            double targetDR = (selectedLandingX + 0.5) * BLOCKSIDELENGTH;
            double targetUR = (selectedLandingY + 0.5) * BLOCKSIDELENGTH;

            int ret = HumanMove(transport->SN, targetDR, targetUR);
            if (ret > 0) {
                updateTransportState(transport->SN, TRANSPORT_IDLE, info);
                DebugText("运输船 " + std::to_string(transport->SN) + " 出发前往预选登陆点");
            }
        }
    }
}

void UsrAI::handleTransportReturn(const tagFarmer* transport, const tagInfo& info) {
    // 如果运输船正在移动，等待
    if (transport->NowState == HUMAN_STATE_WALKING) {
        DebugText("运输船 " + std::to_string(transport->SN) + " 正在返回中...");

        // 检查是否已经接近家乡
        int distFromHome = abs(transport->BlockDR - center_x) + abs(transport->BlockUR - center_y);
        if (distFromHome <= 35) {
            DebugText("运输船 " + std::to_string(transport->SN) + " 已返回家乡附近");
            updateTransportState(transport->SN, TRANSPORT_IDLE, info);
        }
        return;
    }

    // 如果空闲，检查是否已到达家乡
    int distFromHome = abs(transport->BlockDR - center_x) + abs(transport->BlockUR - center_y);
    if (distFromHome <= 35) {
        DebugText("运输船 " + std::to_string(transport->SN) + " 已在家乡附近");
        updateTransportState(transport->SN, TRANSPORT_IDLE, info);
        return;
    }

    // 否则继续返回
    DebugText("运输船 " + std::to_string(transport->SN) + " 继续返回家乡");
    executeTransportReturn(transport, info);
}

void UsrAI::handleTransportRelocating(const tagFarmer* transport, const tagInfo& info) {
    // 如果运输船正在移动，等待
    if (transport->NowState == HUMAN_STATE_WALKING) {
        // 检查是否到达海洋
        int currentTerrain = (*info.theMap)[transport->BlockDR][transport->BlockUR].type;
        if (currentTerrain == MAPPATTERN_OCEAN) {
            updateTransportState(transport->SN, TRANSPORT_IDLE, info);
            DebugText("运输船 " + std::to_string(transport->SN) + " 成功到达海洋");
        }
        return;
    }

    // 重新尝试移动到海洋
    relocateTransportToOcean(transport, info);
}

void UsrAI::relocateTransportToOcean(const tagFarmer* transport, const tagInfo& info) {
    int nearestOceanX = -1, nearestOceanY = -1;
    double minDist = 999999;

    for (int dx = -10; dx <= 10; dx++) {
        for (int dy = -10; dy <= 10; dy++) {
            int checkX = transport->BlockDR + dx;
            int checkY = transport->BlockUR + dy;

            if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                    double dist = sqrt(dx*dx + dy*dy);
                    if (dist < minDist) {
                        minDist = dist;
                        nearestOceanX = checkX;
                        nearestOceanY = checkY;
                    }
                }
            }
        }
    }

    if (nearestOceanX != -1 && nearestOceanY != -1) {
        // 普通移动使用0.5偏移
        double targetDR = (nearestOceanX + 0.5) * BLOCKSIDELENGTH;
        double targetUR = (nearestOceanY + 0.5) * BLOCKSIDELENGTH;

        int ret = HumanMove(transport->SN, targetDR, targetUR);
        if (ret > 0) {
            updateTransportState(transport->SN, TRANSPORT_RELOCATING, info);
            DebugText("运输船 " + std::to_string(transport->SN) + " 移动到海洋位置");
        }
    }
}

void UsrAI::moveTransportToCoast(const tagFarmer* transport, const tagInfo& info) {
    // 如果运输船正在移动，不要发送新命令
    if (transport->NowState == HUMAN_STATE_WALKING) {
        DebugText("运输船 " + std::to_string(transport->SN) +
                  " 已在移动中，跳过新命令");
        return;
    }

    DebugText("开始寻找海岸位置，运输船当前位置: (" +
              std::to_string(transport->BlockDR) + "," +
              std::to_string(transport->BlockUR) + ")");

    int targetBlockX = -1, targetBlockY = -1;
    double minDist = 999999;

    // 方案1：先从运输船当前位置附近搜索
    const int localSearchRadius = 10;
    for (int dx = -localSearchRadius; dx <= localSearchRadius; dx++) {
        for (int dy = -localSearchRadius; dy <= localSearchRadius; dy++) {
            int x = transport->BlockDR + dx;
            int y = transport->BlockUR + dy;

            if (x >= 0 && x < 128 && y >= 0 && y < 128) {
                if ((*info.theMap)[x][y].type == MAPPATTERN_OCEAN) {
                    // 检查所有8个方向是否邻近陆地
                    const int offsets[8][2] = {
                        {-1, 0}, {1, 0}, {0, -1}, {0, 1},
                        {-1, -1}, {-1, 1}, {1, -1}, {1, 1}
                    };

                    int adjacentLandCount = 0;

                    for (const auto& offset : offsets) {
                        int landX = x + offset[0];
                        int landY = y + offset[1];

                        if (landX >= 0 && landX < 128 && landY >= 0 && landY < 128) {
                            if ((*info.theMap)[landX][landY].type == MAPPATTERN_GRASS) {
                                adjacentLandCount++;
                            }
                        }
                    }

                    if (adjacentLandCount > 0) {
                        // 找到海岸
                        double dist = sqrt(pow(x - transport->BlockDR, 2) +
                                         pow(y - transport->BlockUR, 2));

                        // 优先选择有更多陆地相邻的位置（更好的靠岸点）
                        double weightedDist = dist - adjacentLandCount * 3;

                        if (weightedDist < minDist) {
                            minDist = weightedDist;
                            targetBlockX = x;
                            targetBlockY = y;
                        }
                    }
                }
            }
        }
    }

    // 方案2：如果附近没找到，再在家乡附近搜索
    if (targetBlockX == -1) {
        DebugText("运输船附近未找到海岸，搜索家乡附近");

        for (int x = center_x - 20; x <= center_x + 20; x++) {
            for (int y = center_y - 20; y <= center_y + 20; y++) {
                if (x >= 0 && x < 128 && y >= 0 && y < 128) {
                    if ((*info.theMap)[x][y].type == MAPPATTERN_OCEAN) {
                        // 同样的海岸检测逻辑
                        const int offsets[8][2] = {
                            {-1, 0}, {1, 0}, {0, -1}, {0, 1},
                            {-1, -1}, {-1, 1}, {1, -1}, {1, 1}
                        };

                        int adjacentLandCount = 0;

                        for (const auto& offset : offsets) {
                            int landX = x + offset[0];
                            int landY = y + offset[1];

                            if (landX >= 0 && landX < 128 && landY >= 0 && landY < 128) {
                                if ((*info.theMap)[landX][landY].type == MAPPATTERN_GRASS) {
                                    adjacentLandCount++;
                                }
                            }
                        }

                        if (adjacentLandCount > 0) {
                            double dist = sqrt(pow(x - transport->BlockDR, 2) +
                                             pow(y - transport->BlockUR, 2));

                            if (dist < minDist) {
                                minDist = dist;
                                targetBlockX = x;
                                targetBlockY = y;
                            }
                        }
                    }
                }
            }
        }
    }

    if (targetBlockX != -1 && targetBlockY != -1) {
        // 装载村民时使用0.2偏移
        double targetDR = (targetBlockX + 0.2) * BLOCKSIDELENGTH;
        double targetUR = (targetBlockY + 0.2) * BLOCKSIDELENGTH;

        DebugText("选择海岸位置(装载): 块坐标(" + std::to_string(targetBlockX) + "," +
                  std::to_string(targetBlockY) + "), 细节坐标(" +
                  std::to_string(targetDR) + "," + std::to_string(targetUR) + ")");

        int ret = HumanMove(transport->SN, targetDR, targetUR);

        if (ret > 0) {
            DebugText("运输船 " + std::to_string(transport->SN) + " 移动命令成功");
        } else {
            DebugText("运输船移动失败，错误码: " + std::to_string(ret));
        }
    } else {
        DebugText("错误：未找到合适的海岸位置");
    }
}

void UsrAI::loadVillagersOntoSingleTransport(const tagFarmer* transport, const tagInfo& info) {
    int villagersNeeded = 5 - transport->Resource;
    if (villagersNeeded <= 0) {
        return;
    }

    const double BLOCK_SIZE = 35.7;  // 使用精确的常量
    std::vector<std::pair<int, double>> availableVillagers;

    // 使用细节坐标计算距离，更精确
    for (const auto& villager : info.farmers) {
        if (villager.FarmerSort == 0) {  // 陆地村民
            // 使用细节坐标计算实际距离
            double detailDist = sqrt(pow(villager.DR - transport->DR, 2) +
                                   pow(villager.UR - transport->UR, 2));

            // 放宽距离限制，使用细节坐标距离（约25格的细节距离）
            if (detailDist < 25 * BLOCK_SIZE) {  // 约892.5单位的细节距离
                if (villager.NowState == HUMAN_STATE_IDLE) {
                    availableVillagers.push_back(std::make_pair(villager.SN, detailDist));
                }
                else if (villager.NowState == HUMAN_STATE_WORKING) {
                    // 检查是否在关键工作
                    bool criticalWork = false;
                    if (info.Wood < 100 || info.Meat < 100) {
                        criticalWork = true;
                    }

                    if (!criticalWork) {
                        availableVillagers.push_back(std::make_pair(villager.SN, detailDist + 1000 * BLOCK_SIZE));
                    }
                }
            }
        }
    }

    // 按距离排序
    std::sort(availableVillagers.begin(), availableVillagers.end(),
             [](const std::pair<int, double>& a, const std::pair<int, double>& b) {
                 return a.second < b.second;
             });

    int boardingCommands = 0;
    for (size_t i = 0; i < availableVillagers.size() && boardingCommands < villagersNeeded; i++) {
        int villagerSN = availableVillagers[i].first;

        // 确认村民仍然存在
        bool villagerExists = false;
        for (const auto& v : info.farmers) {
            if (v.SN == villagerSN && v.FarmerSort == 0) {
                if (v.NowState == HUMAN_STATE_WORKING) {
                    // 先停止工作，移动到当前位置
                    HumanMove(villagerSN, v.DR, v.UR);
                }
                villagerExists = true;
                break;
            }
        }

        if (villagerExists) {
            int ret = HumanAction(villagerSN, transport->SN);
            if (ret > 0) {
                boardingCommands++;
                DebugText("村民 " + std::to_string(villagerSN) + " 登上运输船 " +
                         std::to_string(transport->SN) + " (距离: " +
                         std::to_string(availableVillagers[i].second / BLOCK_SIZE) + " 格)");
            } else {
                DebugText("村民 " + std::to_string(villagerSN) + " 上船失败，错误码: " +
                         std::to_string(ret));

                // 如果是距离问题，让村民靠近运输船
                if (ret == ACTION_INVALID_DISTANCE_FAR) {
                    // 让村民移动到运输船附近
                    HumanMove(villagerSN, transport->DR, transport->UR);
                    DebugText("村民距离太远，命令其靠近运输船");
                }
            }
        }
    }

    if (boardingCommands > 0) {
        DebugText("本轮命令 " + std::to_string(boardingCommands) + " 个村民上船");
    } else if (availableVillagers.empty()) {
        DebugText("附近没有可用村民");
    }
}

void UsrAI::manageTransportShipProduction(const tagInfo& info) {
    if (transportShipCount >= 1) {
        return;
    }

    for (const auto& building : info.buildings) {
        if (building.Type == BUILDING_DOCK && building.Percent == 100 && building.Project == 0) {
            if (info.Wood >= BUILDING_DOCK_CREATE_WOOD_BOAT_WOOD) {
                int ret = BuildingAction(building.SN, BUILDING_DOCK_CREATE_WOOD_BOAT);
                if (ret > 0) {
                    dockTransportShipCount[building.SN]++;
                }
            } else {
                ;
            }
        }
    }
}

void UsrAI::scanForEnemyContinent(const tagInfo& info) {
    if (enemyContinentFound) return;

    enemyLandPositions.clear();
    landingPositions.clear();

    for (int x = 0; x < 128; x++) {
        for (int y = 0; y < 128; y++) {
            if ((*info.theMap)[x][y].type == MAPPATTERN_GRASS) {
                int dist = abs(x - center_x) + abs(y - center_y);
                if (dist > 40) {
                    enemyLandPositions.push_back(std::make_pair(x, y));
                    if (!enemyContinentFound) {
                        enemyContinentX = x;
                        enemyContinentY = y;
                        enemyContinentFound = true;
                    }

                    bool isCoastal = false;
                    const int offsets[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
                    for (const auto& offset : offsets) {
                        int checkX = x + offset[0];
                        int checkY = y + offset[1];
                        if (checkX >= 0 && checkX < 128 && checkY >= 0 && checkY < 128) {
                            if ((*info.theMap)[checkX][checkY].type == MAPPATTERN_OCEAN) {
                                isCoastal = true;
                                break;
                            }
                        }
                    }

                    if (isCoastal) {
                        int landCount = 0;
                        for (int dx = -2; dx <= 2; dx++) {
                            for (int dy = -2; dy <= 2; dy++) {
                                int nearX = x + dx;
                                int nearY = y + dy;
                                if (nearX >= 0 && nearX < 128 && nearY >= 0 && nearY < 128) {
                                    if ((*info.theMap)[nearX][nearY].type == MAPPATTERN_GRASS) {
                                        landCount++;
                                    }
                                }
                            }
                        }

                        if (landCount >= 10) {
                            landingPositions.push_back(std::make_pair(x, y));
                        }
                    }
                }
            }
        }
    }

    if (!landingPositions.empty()) {
        int bestX = -1, bestY = -1;
        double bestScore = -999999;

        for (const auto& pos : landingPositions) {
            double score = 0;

            double distFromHome = sqrt(pow(pos.first - center_x, 2) + pow(pos.second - center_y, 2));
            score += distFromHome;

            for (const auto& enemy : info.enemy_armies) {
                double dist = sqrt(pow(pos.first - enemy.BlockDR, 2) + pow(pos.second - enemy.BlockUR, 2));
                if (dist < 15) {
                    score -= 20;
                }
            }

            for (const auto& enemy : info.enemy_buildings) {
                double dist = sqrt(pow(pos.first - enemy.BlockDR, 2) + pow(pos.second - enemy.BlockUR, 2));
                if (dist < 10) {
                    score -= 30;
                }
            }

            if (score > bestScore) {
                bestScore = score;
                bestX = pos.first;
                bestY = pos.second;
            }
        }

        if (bestX != -1) {
            selectedLandingX = bestX;
            selectedLandingY = bestY;
        }
    } else {
        ;
    }
}

void UsrAI::loadArmyOntoTransports(const tagInfo& info) {
    std::vector<int> idleTransports;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 1 && farmer.NowState == HUMAN_STATE_IDLE && farmer.Resource < 5) {
            idleTransports.push_back(farmer.SN);
        }
    }

    if (idleTransports.empty()) return;

    for (const auto& army : info.armies) {
        if (boardedUnits.count(army.SN)) continue;

        if (army.Sort != AT_SHIP) {
            for (int transportSN : idleTransports) {
                int ret = HumanAction(army.SN, transportSN);
                if (ret > 0) {
                    boardedUnits.insert(army.SN);
                    break;
                }
            }
        }
    }
}

std::pair<int, int> UsrAI::getWarshipFleetCenter(const tagInfo& info) {
    double totalX = 0, totalY = 0;
    int count = 0;

    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) {
            totalX += army.BlockDR;
            totalY += army.BlockUR;
            count++;
        }
    }

    if (count > 0) {
        return {(int)(totalX / count), (int)(totalY / count)};
    }

    // 如果没有战船，返回一个默认位置
    return {-1, -1};
}

bool UsrAI::findNearestCoastalToFleet(int& x, int& y, const std::pair<int, int>& fleetPos, const tagInfo& info) {
    if (fleetPos.first == -1 || fleetPos.second == -1) {
        return false;
    }

    int bestX = -1, bestY = -1;
    double minDist = 999999;

    // 在战船舰队附近搜索合适的海岸
    const int searchRadius = 20;

    for (int dx = -searchRadius; dx <= searchRadius; dx++) {
        for (int dy = -searchRadius; dy <= searchRadius; dy++) {
            int checkX = fleetPos.first + dx;
            int checkY = fleetPos.second + dy;

            if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128) continue;

            // 检查是否是陆地
            if ((*info.theMap)[checkX][checkY].type != MAPPATTERN_GRASS) continue;

            // 检查是否靠海
            bool isCoastal = false;
            for (int ddx = -1; ddx <= 1; ddx++) {
                for (int ddy = -1; ddy <= 1; ddy++) {
                    if (ddx == 0 && ddy == 0) continue;
                    int adjX = checkX + ddx;
                    int adjY = checkY + ddy;
                    if (adjX >= 0 && adjX < 128 && adjY >= 0 && adjY < 128) {
                        if ((*info.theMap)[adjX][adjY].type == MAPPATTERN_OCEAN) {
                            isCoastal = true;
                            break;
                        }
                    }
                }
                if (isCoastal) break;
            }

            if (isCoastal) {
                double dist = sqrt(pow(checkX - fleetPos.first, 2) + pow(checkY - fleetPos.second, 2));
                if (dist < minDist) {
                    minDist = dist;
                    bestX = checkX;
                    bestY = checkY;
                }
            }
        }
    }

    if (bestX != -1 && bestY != -1) {
        x = bestX;
        y = bestY;
        return true;
    }

    return false;
}


bool UsrAI::findHomeCoastalPosition(int& x, int& y, const tagInfo& info) {
    const int searchRadius = 20;
    int bestX = -1, bestY = -1;
    double minDist = 999999;

    for (int dx = -searchRadius; dx <= searchRadius; dx++) {
        for (int dy = -searchRadius; dy <= searchRadius; dy++) {
            int checkX = center_x + dx;
            int checkY = center_y + dy;

            if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128) continue;

            if ((*info.theMap)[checkX][checkY].type != MAPPATTERN_GRASS) continue;

            bool isCoastal = false;
            const int offsets[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
            for (const auto& offset : offsets) {
                int adjX = checkX + offset[0];
                int adjY = checkY + offset[1];
                if (adjX >= 0 && adjX < 128 && adjY >= 0 && adjY < 128) {
                    if ((*info.theMap)[adjX][adjY].type == MAPPATTERN_OCEAN) {
                        isCoastal = true;
                        break;
                    }
                }
            }

            if (isCoastal) {
                double dist = sqrt(pow(checkX - center_x, 2) + pow(checkY - center_y, 2));
                if (dist < minDist) {
                    minDist = dist;
                    bestX = checkX;
                    bestY = checkY;
                }
            }
        }
    }

    if (bestX != -1) {
        x = bestX;
        y = bestY;
        return true;
    }
    return false;
}

void UsrAI::manageCombat(const tagInfo& info) {
    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) continue;
        if (army.NowState != HUMAN_STATE_IDLE) continue;

        int nearestEnemySN = -1;
        double minDist = 999999;

        for (const auto& enemy : info.enemy_armies) {
            double dist = sqrt(pow(army.BlockDR - enemy.BlockDR, 2) +
                             pow(army.BlockUR - enemy.BlockUR, 2));
            if (dist < minDist) {
                minDist = dist;
                nearestEnemySN = enemy.SN;
            }
        }

        for (const auto& enemy : info.enemy_buildings) {
            if (enemy.Type == BUILDING_ARROWTOWER) {
                double dist = sqrt(pow(army.BlockDR - enemy.BlockDR, 2) +
                                 pow(army.BlockUR - enemy.BlockUR, 2));
                if (dist < minDist) {
                    minDist = dist;
                    nearestEnemySN = enemy.SN;
                }
            }
        }

        if (nearestEnemySN != -1 && minDist < 20) {
            HumanAction(army.SN, nearestEnemySN);
        }
    }
}

void UsrAI::collectGoldPhase(const tagInfo& info) {
    goldCollected = info.Gold;

    if (goldCollected >= TARGET_GOLD) {
        return;
    }

    villagersTransported = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 0) {
            int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
            if (dist > 40) {
                villagersTransported++;
            }
        }
    }

    if (!goldPositions.empty()) {
        for (const auto& farmer : info.farmers) {
            if (farmer.FarmerSort == 0 && farmer.NowState == HUMAN_STATE_IDLE) {
                int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
                if (dist > 40) {
                    int nearestGoldSN = -1;
                    double minDist = 999999;
                    for (const auto& res : info.resources) {
                        if (res.Type == RESOURCE_GOLD && res.Cnt > 0) {
                            double d = abs(farmer.BlockDR - res.BlockDR) + abs(farmer.BlockUR - res.BlockUR);
                            if (d < minDist) {
                                minDist = d;
                                nearestGoldSN = res.SN;
                            }
                        }
                    }

                    if (nearestGoldSN != -1) {
                        HumanAction(farmer.SN, nearestGoldSN);
                        goldMiners.insert(farmer.SN);
                    }
                }
            }
        }
    }

    this->protectGoldMiners(info);
    this->manageCombat(info);
    this->assignTasksToVillagersWithLimits(info, false);
}

void UsrAI::transportVillagersToGold(const tagInfo& info) {
    int villagersOnEnemyContinent = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 0) {
            int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
            if (dist > 40) {
                villagersOnEnemyContinent++;
            }
        }
    }

    if (villagersOnEnemyContinent < TARGET_GOLD_MINERS) {
        int totalVillagers = 0;
        for (const auto& farmer : info.farmers) {
            if (farmer.FarmerSort == 0) totalVillagers++;
        }

        if (totalVillagers < 25 && info.Meat >= BUILDING_CENTER_CREATEFARMER_FOOD) {
            for (const auto& building : info.buildings) {
                if (building.Type == BUILDING_CENTER && building.Percent == 100 && building.Project == 0) {
                    if ((info.farmers.size() + info.armies.size()) < info.Human_MaxNum) {
                        int ret = BuildingAction(building.SN, BUILDING_CENTER_CREATEFARMER);
                        if (ret > 0) {
                            return;
                        }
                    }
                }
            }
        }

        std::vector<int> homeVillagers;
        for (const auto& farmer : info.farmers) {
            if (farmer.FarmerSort == 0) {
                int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
                if (dist < 30) {
                    if (farmer.NowState == HUMAN_STATE_IDLE) {
                        homeVillagers.push_back(farmer.SN);
                    } else if (farmer.NowState == HUMAN_STATE_WORKING) {
                        bool isCritical = false;
                        for (const auto& res : info.resources) {
                            if (res.SN == farmer.WorkObjectSN) {
                                if (res.Type == RESOURCE_TREE && info.Wood < 200) {
                                    isCritical = true;
                                }
                                break;
                            }
                        }
                        if (!isCritical) {
                            HumanMove(farmer.SN, farmer.DR, farmer.UR);
                            homeVillagers.push_back(farmer.SN);
                        }
                    }
                }
            }
        }

        for (const auto& farmer : info.farmers) {
            if (farmer.FarmerSort == 1) {
                int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
                if (dist < 30 && farmer.Resource < 5) {
                    int loaded = 0;
                    for (int villagerSN : homeVillagers) {
                        if (farmer.Resource + loaded >= 5) break;
                        HumanAction(villagerSN, farmer.SN);
                        loaded++;
                    }
                }

                if (farmer.Resource > 0 && !goldPositions.empty()) {
                    if (selectedLandingX != -1 && selectedLandingY != -1) {
                        HumanMove(farmer.SN, selectedLandingX * BLOCKSIDELENGTH,
                                selectedLandingY * BLOCKSIDELENGTH);
                    }
                }
            }
        }

        for (const auto& farmer : info.farmers) {
            if (farmer.FarmerSort == 1 && farmer.Resource == 0 && farmer.NowState == HUMAN_STATE_IDLE) {
                int dist = abs(farmer.BlockDR - center_x) + abs(farmer.BlockUR - center_y);
                if (dist > 40) {
                    int coastX, coastY;
                    if (findCoastalLandingPosition(coastX, coastY, info)) {
                        HumanMove(farmer.SN, coastX * BLOCKSIDELENGTH, coastY * BLOCKSIDELENGTH);
                    }
                }
            }
        }
    }
}

void UsrAI::protectGoldMiners(const tagInfo& info) {
    if (goldPositions.empty()) return;

    int goldX = goldPositions[0].first;
    int goldY = goldPositions[0].second;

    int radius = 5;
    int unitCount = 0;

    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) continue;
        if (army.NowState != HUMAN_STATE_IDLE) continue;

        double angle = (unitCount * 2 * 3.14159) / 8;
        int targetX = goldX + (int)(radius * cos(angle));
        int targetY = goldY + (int)(radius * sin(angle));

        if (targetX >= 0 && targetX < 128 && targetY >= 0 && targetY < 128) {
            HumanMove(army.SN, targetX * BLOCKSIDELENGTH, targetY * BLOCKSIDELENGTH);
            unitCount++;
        }
    }
}

bool UsrAI::findSafeLandingPosition(int& x, int& y, const tagInfo& info) {
    double maxSafety = -1;
    int bestX = -1, bestY = -1;

    for (const auto& pos : landingPositions) {
        double minEnemyDist = 999999;

        for (const auto& enemy : info.enemy_armies) {
            double dist = sqrt(pow(pos.first - enemy.BlockDR, 2) +
                             pow(pos.second - enemy.BlockUR, 2));
            if (dist < minEnemyDist) {
                minEnemyDist = dist;
            }
        }

        if (minEnemyDist > maxSafety) {
            maxSafety = minEnemyDist;
            bestX = pos.first;
            bestY = pos.second;
        }
    }

    if (bestX != -1) {
        x = bestX;
        y = bestY;
        return true;
    }

    return false;
}

bool UsrAI::findHomeCoastalLandPosition(int& x, int& y, const tagInfo& info) {
    const int searchRadius = 15;
    int bestX = -1, bestY = -1;
    double minDist = 999999;

    for (int dx = -searchRadius; dx <= searchRadius; dx++) {
        for (int dy = -searchRadius; dy <= searchRadius; dy++) {
            int checkX = center_x + dx;
            int checkY = center_y + dy;

            if (checkX < 0 || checkY < 0 || checkX >= 128 || checkY >= 128) continue;

            if ((*info.theMap)[checkX][checkY].type != MAPPATTERN_GRASS) continue;

            bool isCoastal = false;
            for (int ddx = -1; ddx <= 1; ddx++) {
                for (int ddy = -1; ddy <= 1; ddy++) {
                    if (ddx == 0 && ddy == 0) continue;
                    int adjX = checkX + ddx;
                    int adjY = checkY + ddy;
                    if (adjX >= 0 && adjX < 128 && adjY >= 0 && adjY < 128) {
                        if ((*info.theMap)[adjX][adjY].type == MAPPATTERN_OCEAN) {
                            isCoastal = true;
                            break;
                        }
                    }
                }
                if (isCoastal) break;
            }

            if (isCoastal) {

                double dist = sqrt(pow(checkX - center_x, 2) + pow(checkY - center_y, 2));
                if (dist < minDist) {
                    minDist = dist;
                    bestX = checkX;
                    bestY = checkY;
                }
            }
        }
    }

    if (bestX != -1) {
        x = bestX;
        y = bestY;
        return true;
    }
    return false;
}


void UsrAI::processData() {
    tagInfo info = getInfo();

    houseCount = 0;
    housesUnderConstruction = 0;
    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_HOME) {
            if (b.Percent == 100) houseCount++;
            else housesUnderConstruction++;
        }
    }

    stockBuilt = false;
    dockBuilt = false;
    dockConstructionStarted = false;
    totalDocksPresent = 0;
    completedDocksCount = 0;
    for (const auto& b : info.buildings) {
        if (b.Type == BUILDING_STOCK && b.Percent == 100) stockBuilt = true;
        if (b.Type == BUILDING_DOCK) {
            totalDocksPresent++;
            if (b.Percent == 100) {
                dockBuilt = true;
                completedDocksCount++;
            }
            if (b.Percent < 100) dockConstructionStarted = true;
        }
    }

    fishingBoatCount = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 2) fishingBoatCount++;
    }

    warshipCount = 0;
    for (const auto& army : info.armies) {
        if (army.Sort == AT_SHIP) warshipCount++;
    }

    transportShipCount = 0;
    for (const auto& farmer : info.farmers) {
        if (farmer.FarmerSort == 1) transportShipCount++;
    }

    if (!upgradeStarted) {
        for (const auto& building : info.buildings) {
            if (building.Type == BUILDING_CENTER && building.Project == BUILDING_CENTER_UPGRADE) {
                upgradeStarted = true;
                ordinaryVillagers.clear();
                break;
            }
        }
    }

    if (toolAgeBuilderSN != -1 && toolAgeBuilderBusy) {
        bool builderStillBusy = false;

        for (const auto& farmer : info.farmers) {
            if (farmer.SN == toolAgeBuilderSN) {
                if (farmer.NowState != HUMAN_STATE_IDLE) {
                    builderStillBusy = true;
                }
                break;
            }
        }

        if (!builderStillBusy) {
            toolAgeBuilderBusy = false;
        }
    }

    if (upgradeStarted && info.civilizationStage == CIVILIZATION_TOOLAGE) {
        upgradeStarted = false;
        toolAgeInitialized = false;

        villagersToProduceAfterUpgrade = 6;
        villagersProducedAfterUpgrade = 0;
        currentStage = STAGE_AFTER_UPGRADE;
    }

    if (upgradeStarted) {
        this->assignTasksToVillagersWithLimits(info, false);
    }

    switch(currentStage) {
        case STAGE_INITIAL:
            if (!centerInitialized) this->initializeCenter(info);
            break;

        case STAGE_BUILD_HOUSES:
            this->buildHousesPhase(info);
            break;

        case STAGE_POPULATION_GROWTH:
            this->populationGrowthPhase(info);
            break;

        case STAGE_COLLECT_RESOURCES:
            this->collectResourcesPhase(info);
            break;

        case STAGE_BUILD_REQUIRED_BUILDINGS:
            this->buildRequiredBuildingsPhase(info);
            break;

        case STAGE_UPGRADE_AGE:
            this->upgradeAgePhase(info);
            break;

        case STAGE_BUILD_FISHING_BOAT:
            this->buildFishingBoatPhase(info);
            break;

        case STAGE_AFTER_UPGRADE:
            if (!upgradeStarted) {
                this->afterUpgradePhase(info);
            }
            break;

        case STAGE_BUILD_WARSHIPS:
            this->buildWarshipsPhase(info);
            break;

        case STAGE_BUILD_ARMY:
            this->buildArmyPhase(info);
            break;

        case STAGE_LAND_INVASION:
            this->landInvasionPhase(info);
            break;

        case STAGE_COLLECT_GOLD:
            this->collectGoldPhase(info);
            break;

        case STAGE_EXPLORE:
            this->explorePhase(info);
            break;
    }

    // 统一管理运输船 - 替换原来分散的运输船控制调用
    this->manageTransportShips(info);

    if (currentStage >= STAGE_BUILD_ARMY) {
        this->manageTransportShipProduction(info);
    }

    this->assignFishingBoatsToFishResources(info);

    prevInfo = info;
}

